Get the say command to read numbers in ordinal form. “First”,not ”one”

Hello,

If I run the script below:


repeat with i from 1 to 10
say i
end repeat

It will say “one, two, three, four”, etc.

Is there a way to get it read it ordinally?

“First, second, third, fourth”, etc.

I know Applescript can understand ordinal numbers in code, but how can I get the “say” command to read 1 as “first”, 2 as “second”, 3 as “third”, etc?

Do we have to create a handler with special rules for ordinal numbers?

AppleScript isn’t going to interpret the integers that way. (Remember, it’s just a dumb computer doing what it’s told).

Here are two simple approaches…


repeat with a in {"first", "second", "third"}
	say a
end repeat


property ordinals : {"first", "second", "third"}

repeat with a from 1 to 3
	say my ordinal(a)
end repeat

on ordinal(a)
	return item a of ordinals
end ordinal

Hi.

This may be what you need:

(* Append an ordinal suffix to a number. *)
-- Adapted from Victor Yee (adapted from NG (adapted from Jason Bourque) & Paul Skinner)
on ordinalise(n)
	set units to n mod 10
	if (units > 3) or ((n - units) mod 100 is 10) or (units < 1) or (units mod 1 > 0) then return (n as text) & "th"
	return (n as text) & item units of {"st", "nd", "rd"}
end ordinalise

repeat with i from 1 to 10
	say ordinalise(i)
end repeat

Another suggestion:

repeat with i from 1 to 10
	say addSuffix(i)
end repeat

on addSuffix(theNumber)
	set theSuffix to "th"
	set lastDigit to theNumber mod 10
	if (theNumber mod 100) is not in {11, 12, 13} and lastDigit is in {1, 2, 3} then
		set theSuffix to item lastDigit of {"st", "nd", "rd"} -- from Nigel's script
	end if
	return (theNumber as string) & theSuffix
end addSuffix

My script originally based on:
https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/ManipulateNumbers.html

You can use a number formatter:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions

-- classes, constants, and enums used
property NSNumberFormatterOrdinalStyle : a reference to 6

set nf to current application's NSNumberFormatter's new()
nf's setNumberStyle:(NSNumberFormatterOrdinalStyle)
repeat with i from 1 to 10
	set theText to (nf's stringFromNumber:i) as text
	say theText
end repeat

Thanks everybody. The above scripts will do.

I find it strange that since AppleScript has a native ability to understand ordinal numbers, but it doesn’t have the native ability in reverse.

For example, something like:

Get first item of theList
Get eleventh item of theList

Are both valid code and gets item 1 and item 11 respectively. So it looks like AppleScript can natively convert ordinal to cardinal, but not in reverse.

I was hoping there would be some kind of simple syntax like:

say 5 as ordinal

But the above handlers will work just fine.

Hello Shane.
Is there a setting allowing the formatter to return: first, second, third, not 1st, 2nd, 3rd ?
Same question of course to get : premier, deuxième, troisième, not 1er, e2, 3e.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 21 juillet 2020 12:38:35

eleventh item of theList isn’t valid AppleScript code. The terms from first to tenth are AppleScript keywords, but there are none for higher ordinals. There are also the keywords th, st, nd, and rd, which can be used as suffixes with integers in specifier contexts …

get 11th item of theList

… but these are different ways of writing index specifiers rather than conversions from cardinals to ordinals.

Alas, no.

It looks like the say command is pretty flexible, at least in English:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions

set nf to current application's NSNumberFormatter's new()
nf's setNumberStyle:(current application's NSNumberFormatterOrdinalStyle)
set theText to (nf's stringFromNumber:1.5) as text
say theText --> speaks "second"
return theText --> "2st"

Thank you Shane

I didn’t took, care that my sound level was set to 0.

Resetting it, I discovered that the say command correctly said : premier, deuxième, troisième…

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 21 juillet 2020 15:14:51

Yes, the number formatter version has the advantage of being language agnostic.

I wanted to understand the second of the above lines from Nigel’s script and to do that broke it down into individual tests. I think I understand 1 through 3 but I don’t understand the reason for 4. Thanks.

  1. units > 3 → numbers ending with 4 thru 9 use th suffix

  2. (n - units) mod 100 is 10 – numbers equal to or ending with 10, 11, 12, 13 use th suffix

  3. units < 1 – numbers ending with 0 use th suffix

  4. units mod 1 > 0 – ???

Hi peavine.

I think when the handler was written, (units < 1) was supposed to catch both multiples of 10 and negatives. Negatives themselves obviously make no sense as ordinals, but you might be moved to express them that way when talking about negatively indexed items in, say, a list. “The item you need is the -5th in the list.” If ordinal suffixes are used with negative index specifiers in a script, they all get compiled to the “th” form, so I went with that for all negatives:

-2nd item of {1, 2, 3, 4}
-- Compiles as:
-2th item of {1, 2, 3, 4}

(units mod 1 > 0) catches fractional numbers and was similarly intended more to allow one to express oneself that way than to represent actual ordinals. I think it’s actually superfluous as the same results are returned without it. Or perhaps it should be (class of units is real), which would catch .0 too.

If you know ahead of time that the input is going to be a positive integer, then there’s no need to do anything special beyond appending an(y) ordinal suffix:

set i to 1
say i & "nd" as text --> says "first"

You also have to know ahead of time that the result’s only going to be used by the ‘say’ command and that AppleScript’s text item delimiters will be at their default value. The latter can be ignored if ‘as text’ is placed after i instead of after “nd”. :slight_smile:

Good point, well spotted. Alternatively, [format]say “” & i & “nd”[/format]or[format]say [i, “nd”] as text[/format]also negate the worry.

Title of post: Get the say command to read numbers in ordinal form.

Square brackets aren’t part of AppleScript and shouldn’t be used, even to ignore the TIDs.

Thanks Nigel for explaining those tests in your script. What you say makes sense.

How rigid. I suggest it is a part of AppleScript, albeit undocumented/deprecated, and there’s absolutely no reason to believe the AppleScript engineers are going to go to any trouble to specifically remove it as a viable syntax, together with its associated linked list class.

If you’re going to post code for the benefit/education of others, the absolute first requirements are that it should be correct and that it should be understandable by those reading it. If you do see fit to post non-standard/undocumented/deprecated things which only happen not to error and which haven’t been mentioned in any version of ASLG or in most other sources in the past twenty-three years, then you should at least point out that this is what they are and explain how they relate to the problems they purport to solve. This should be done up-front at the time of posting, not as an afterthought in order to get sarky with forum moderators or other posters.