文字列より、指定した文字が見つかった位置と総数を報告


ふたたび ときどきの雑記帖 リターンズ - ここまでくると より、ネタをお借りして。


オーソドックスなループ版。

| string index count searchChar |
string := 'I love cat and dog'.
searchChar := $a.
index := 0.
count := 0.

World findATranscript: nil.

Transcript cr; show: ('"{1}"の中から{2}を探します。' format: {string. searchChar}).
[(index := string indexOf: $a startingAt: index+1) > 0] whileTrue: [
   count := count + 1.
   Transcript cr; show: index asString, '文字目で発見しました。'].
Transcript cr; show: '全部で', count asString, '個見つかりました。'
"I love cat and dog"の中からaを探します。
9文字目で発見しました。
12文字目で発見しました。
全部で2個見つかりました。


見つかった位置を保持する版。

| string searchChar foundIndices |
string := 'I love cat and dog'.
searchChar := $a.
foundIndices := OrderedCollection new.

World findATranscript: nil.

Transcript cr; show: ('"{1}"の中から{2}を探します。' format: {string. searchChar}).
string doWithIndex: [:each :idx | each = searchChar
   ifTrue: [Transcript cr; show: (foundIndices add: idx) asString, '文字目で発見しました。']].
Transcript cr; show: ('全部で{1}個見つかりました。' format: {foundIndices size}).
^ foundIndices asArray
"I love cat and dog"の中からaを探します。
9文字目で発見しました。
12文字目で発見しました。
全部で2個見つかりました。
=> #(9 12)

なんかイマイチ。



ところで、#format: の使い方を忘れていたので定義を見ようとしたら同じカテゴリに #expandMacros… シリーズなるメソッド群を見つけました。3.9 での新顔のようです。{} で数字を括るだけの #format: とは別系統で、<> で括って数字 and/or コマンドで埋め込みを指示します。

  • <t> → Character tab
  • <n> → Character cr
  • <インデックスp> → (引数群 at: インデックス) printString
  • <インデックスs> → 引数群 at: インデックス
  • <インデックス?真時テキスト:偽時テキスト>
      → (引数群 at: インデックス) ifTrue: [真時テキスト] ifFalse: [偽時テキスト]
  • %< → $<
'<n>newline<n><t>tab' expandMacros
=> 
newline
	tab
'<1?T:NIL>, <2?T:NIL>, <3p>, <4s>' expandMacrosWith: true with: false with: 'str' with: 'str'
=> T, NIL, 'str', str
'<1?T:NIL>, <2?T:NIL>, <3p>, <4s>' expandMacrosWithArguments: {true. false. 'str'. 'str'}

も上に同じ。


なんかイマイチ。