Each式
each式は、リスト、範囲、またはカスタムイテレータによって提供される各値または選択対象の値のサブセットを収集したり、それらについての情報の生成したりするための強力なメカニズムです。単独のeach式でも、シンプルかつ読みやすい形で多くの処理をこなします。単語、リストおよびテキストアイテム、プロパティリストキー、文字、行などにわたるイテレーションにeach式を利用することができます。each式は、repeatループと結び付いたとき、特にパワーを発揮します。
例:
put each item of 1..50 where each is a multiple of 7 // 「(7,14,21,28,35,42,49)」を表示します
例:
put each item of 1 to 20 where the square root of each is an integer //「(1,4,9,16)」を表示します
例:
put "Mary Mary quite contrary how does your garden grow" into rhyme
put each word of rhyme // 「(Mary,Mary,quite,contrary,how,does,your,garden,grow)」を表示します
put each word of rhyme where the length of each is 4 // 「(Mary,Mary,does,your,grow)」を表示します
put each word of rhyme where each ends with "ary" // 「(Mary,Mary,contrary)」を表示します
put the length of each word of rhyme where each ends with "ary" // 「(4,4,8)」を表示します
put each word of rhyme whose length is 4 and which contains "a" // 「(Mary,Mary)」を表示します
例:
RunWithNewResults TestScript // TestScriptは実行対象のスクリプト名が格納されている変数です
put the result into Outcome
put the long name of each of the files of the folder of Outcome's logfile where each ends with ".png" into myfiles // 結果内の全スクリーンショットへのファイルパスを含んだリストを作成します
SendMail (To:"test@gmail.com",Subject:title & "---Test results" ,body:TestScript & "Results"& Outcome,attachment:Outcome's Logfile &&& myFiles)
Each式の使い方
each式の結果は常にリストになります。最もシンプルな使い方は、each式でソース値の1つ1つの文字、単語、行、テキストアイテム、またはリストアイテムにアクセスし、これらの値を含んだリストを作成することです。
where節を使うと、ある条件に合ったアイテムを選択することができます。where節の中では、each変数がソースからの各値を順に参照します。where節でtrueと評価される値だけが結果のリストに含まれます。
ある条件に合ったアイテムを選択するにあたり、whichまたはwhose節を使うこともできます。1つの式に、whichとwhoseの両方を入れることが可能です。
each式は、いずれかの種類のチャンク(リストアイテム、テキストアイテム、単語、行または文字)と一緒に使用します。
構文:
each chunk of ソース値 {where 条件}
each chunk of ソース値 {(where 条件)}
通常、条件式は特殊変数eachを伴った式で、ソース値の各チャンクに対して設定されます。これにより、結果のリストに含める値を選択します。where節は、読みやすくしたり、文の他の部分から分けたりするために、括弧で囲むことができます。
より大きな式の中のEach式
より大きな式の中にeach式が組み込まれている場合、each式自体からは外れているその他の演算子は、リスト全体ではなく、each式が生成したリストの各値に適用されます。
例:
put the length of each word of "four score and twenty" // each式が("four", "score", "and", "twenty")というリストを生成し、その上でリスト内の各アイテムにlength関数が呼び出され、結果としてその個々の単語の長さのリスト 「(4,5,3,6)」が表示されます
Each式の範囲を限定する
each式の影響はそれを取り囲む式に波及し、式全体が結果のリストの各値に適用されることになります。このことがeach式を格段に強力なものにしている一方、 目的の結果を得るために、この影響力を限定できることも時に重要です。
例:
set text to "the flowers of the forest"
put the number of items in each word of text where the length of each is 3 // each式が("the","the")というリストを返し、その上でこのリストの各アイテムに「number of items in」演算子が適用され、結果として2つの1(単語「the」は1つのアイテムのため)を含んだリスト 「(1,1)」が表示されます
each式の影響範囲を限定するときは、括弧を使用します。
例:
put ("Mars","Venus","Saturn") into planets
put the number of items in each item of planets where the length of each is greater than 4 // リスト「(1,1)」を表示します
put the number of items in (each item of planets where the length of each is greater than 4) // 「the number of items in」がeach式の結果にリスト全体として適用されるため、4文字を超えるリスト内の単語の数が与えられて、 「2」と表示されます
For Each式で範囲を広げる
括弧によってeach式の範囲が限定されるということは、利用できる式の種類に制約が出てきます。例えば、括弧を使った関数は呼び出せなかったり、括弧がeach式の範囲を限定してしまうために各値に適用できなかったりします。このため、関数は、各値ではなく結果のリスト全体に対して呼び出されます。
この問題を克服するには、for each式を使用します。
例:
put round(each,1) for each item of 2.2 to 3.1 by .25 // 「(2.2,2.5,2.7,3)」を表示します
ここに示した式は、特殊なeach変数を使用し、その後にfor eachで始まるeach式を続けています。for eachの前に来る式に特に制約はなく、each変数を何回も使用することができます。次の例に示すように、実行できる演算子の種類には完全な柔軟性があります。
例:
set text to "an ancient anteater sat with my antiquarian aunt"
put "Longest words in text:"
get each & " has " & length(each) & " letters" for each word of text where length(each) > 4
put it joined by return
上記のSenseTalkコードを実行すると、次のように表示されます。
Longest words in text:
ancient has 7 letters
anteater has 8 letters
antiquarian has 11 letters
構文:
結果式 for each chunk of ソース値 {where 条件}
結果式 (for each chunk of ソース値 {where 条件})
通常、条件式は特殊なeach変数を伴った式で、ソース値の各チャンクに対して設定されます。これにより、結果のリストに含める値を選択します。
結果式も、通常は特殊なeach変数を使った式になります。この式は、each式が生成した各値について評価され、式全体としての値の最終リストを生成します。for each節は、読みやすくしたり、文の他の部分から分けたりするために、括弧で囲むことができます。
ネストされたEach式
each式は、別のeach式の中に入れることができます。分かりにくくはなるかもしれませんが、ネストされたリストやその他のネスト構造を扱う際には便利です。例えば、各単語(1つの語句の単語ではなく、一連の語句の各単語)の長さを得たいときは、次のようにして得ることが可能です。
例:
set phrases to {{
universal truth
magic is in the eye of the beholder
all is fair in love and war
}}
put the length of each word of phrases // シングルリスト「(9,5,5,2,2,3,3,2,3,8,3,2,4,2,4,3,3)」を表示します
put the length of each word of each line of phrases // phrasesの行ごとに1リストずつネストされたリスト「((9,5),(5,2,2,3,3,2,3,8),(3,2,4,2,4,3,3))」を表示します
put the number of words of each line of phrases // リスト「(2,8,7)」を表示します
ネストされたeach式でも、where節が使えます。必ず、それぞれのwhere節が一番近くのeachに対応するよう注意してください。例えば、文字数が3文字より多い単語の長さだけを確認したいときは、次の例が使用できます。
例:
set myData to {{
elephant
jelly jar
tea
}}
put the length of each word of each line of myData where true where length of each > 3 //「where true」を使うことで、行の長さではなく、個々の単語の長さに関心があることを示します。長さが3を超える単語を持つ行は1行目と2行目だけのため、ネストされたリスト「((8),(5),())」を表示します
put the length of each word of each line of myData where length of each > 3 // 行内の単語の長さではなく、行の長さを確認します
put the length of each word of each line of myData where length of each > 3 // 行内の単語の長さではなく、行の長さを確認します。長さが3を超える行からのみ単語の長さを格納した、ネストされたリスト「((8),(5,3))」を表示します。
この例で、最初のwhere節のwhere trueは必要です。これがない他方のwhere節は各行に適用されていますが、ここで関心があるのは個々の単語の長さであって、行の長さではないからです。
Each式を結合する
より大きな式の一部として2つのeach式を結合して影響を掛け合わせ、ネストされた結果のリストを生成することもできます。
例:
put each item of "A".."C" & each item of 1..4 // ネストされたリスト「((A1,A2,A3,A4),(B1,B2,B3,B4),(C1,C2,C3,C4))」を表示します
例:
put each item of 1..3 times each item of 1..3 into timesTable // ネストされたリスト「((1,2,3),(2,4,6),(3,6,9))」を変数に格納します
Each式におけるRepeatIndex()
each式と一緒にrepeatindex()関数を使うと、この関数によってソース内の現在のアイテム番号の評価が行われます。詳細は、Repeatループをご覧ください。
例:
put each char of "abcdefg" & repeatIndex() // repeatindexの値に従った番号を文字列の各文字に関連付け、 リスト「(a1,b2,c3,d4,e5,f6,g7)」を表示します
これは、each式の内部で囲っているループからのrepeatIndex()値を必要とする場合には、最初にrepeatIndex()値を変数に割り当てる必要があることも意味します。
例:
set FarmAnimals to {{
pig
cow
chicken
}}
put each line of FarmAnimals & " is on line " & the counter // リスト「(pig is on line 1,cow is on line 2,chicken is on line 3)」を表示します
Repeat With Each
Repeat with eachは、repeatループの一種です。each式と結合されると、文字列を簡単に評価してから、直ちに結果のリストのアイテムに対して各イテレーションの中で演算を実行します。
例:
repeat with each item of ("dog","cat","horse") which starts with "c" // 元のリストを評価して、そこから新しいリスト「(cat)」を作成し、新しいリストの各アイテムを使ってイテレーションを実行します
put it & " meows" // 「cat meows」を表示します
end repeat
例:
repeat with each word of "To infinity and beyond!" whose length is greater than 3
log it // 最初のイテレーションで「infinity」を、2番目のイテレーションで「beyond!」 をログします
typetext it
end repeat