Red/Rebol での文字列の検索は非常に簡単で便利です。発生した問題について、詳細を説明します。
まず第一に、インタプリタはエラーメッセージの形で、何が間違っているかについての良いヒントを与えています: index? expected series argument of type: series port
. これはindex?
、間違ったデータ型で使用したことを意味します。どうしてこうなりました?検索が失敗した場合にfind
関数が値を返すという理由だけで:none
>> str: "abcdefghijklmopqrz"
>> find str "o"
== "pqrz"
>> type? find str "o"
== string!
>> find str "n"
== none
>> type? find str "n"
== none!
したがって、検索が失敗しないことがわかっている場合を除きindex?
、 の結果を直接使用することfind
は安全ではありません。とにかくインデックス情報を抽出する必要がある場合、安全な方法はfind
最初の結果をテストすることです:
>> all [pos: find str "o" index? pos]
== 14
>> all [pos: find str "n" index? pos]
== none
>> if pos: find str "o" [print index? pos]
== 14
>> print either pos: find str "n" [index? pos][-1]
== -1
これらは、ニーズに応じて、それを達成するための安全な方法の例にすぎません。はまたはの条件付きテストnone
として機能するため、そのような場合に使用する必要はありません。false
if
either
found?
ここで、混乱を招いた中心的な問題に光を当てましょう。
Rebol 言語には、データ型の派生元series
であるa と呼ばれる基本的な概念があります。string!
シリーズを正しく理解して使用することは、Rebol 言語を慣用的な方法で使用できるようにするための重要な部分です。シリーズは、他の言語では通常のリストや文字列のようなデータ型のように見えますが、同じではありません。シリーズは次のもので構成されています。
- 値のリスト (文字列の場合は文字のリスト)
- 暗黙的なインデックス (簡単にするためにカーソルと呼ぶことができます)
次の説明は文字列のみに焦点を当てていますが、同じ規則がすべての系列データ型に適用されます。以下の例では、暗黙的なインデックスを整数としてindex?
表示するために関数を使用します。
デフォルトでは、新しい文字列を作成するとき、カーソルは先頭の位置にあります。
>> s: "hello"
>> head? s
== true
>> index? s
== 1
ただし、カーソルを移動して、文字列内の他の場所を指すことができます。
>> next s
== "ello"
>> skip s 3
== "lo"
>> length? skip s 3
== 2
ご覧のとおり、カーソルを移動した文字列はカーソル位置から表示されるだけでなく、他のすべての文字列 (または系列) 関数もその位置を考慮します。
さらに、文字列を指す各参照にカーソルを設定することもできます。
>> a: next s
== "ello"
>> b: skip s 3
== "lo"
>> s: at s 5
== "o"
>> reduce [a b s]
== ["ello" "lo" "o"]
>> reduce [index? a index? b index? s]
== [2 4 5]
ご覧のとおり、特定の文字列 (または系列) に対して必要な数の異なる参照を持つことができ、それぞれに独自のカーソル値がありますが、すべて同じ基になる値のリストを指しています。
シリーズ プロパティの 1 つの重要な結果:他の言語で行うように、文字列 (および他のシリーズ) を操作するために整数インデックスに依存する必要はありません。必要な計算を行うためにシリーズ参照に付属するカーソルを活用するだけで済みます。 、コードは短く、きれいで、非常に読みやすいものになります。それでも、シリーズでは整数インデックスが役立つ場合がありますが、必要になることはほとんどありません。
それでは、文字列を検索するユースケースに戻りましょう。
>> STR: "abcdefghijklmopqrz"
>> find STR "z"
== "z"
>> find STR "n"
== none
必要なのはそれだけです。実行する必要があるほとんどすべての計算に結果の値を使用するために、インデックス位置を抽出する必要はありません。
>> pos: find STR "o"
>> if pos [print "found"]
found
>> print ["sub-string from `o`:" pos]
sub-string from `o`: opqrz
>> length? pos
== 5
>> index? pos
== 14
>> back pos
== "mopqrz"
>> skip pos 4
== "z"
>> pos: find STR "n"
>> print either pos ["found"]["not found"]
not found
>> print either pos [index? pos][-1]
-1
以下は、整数インデックスを明示的に使用せずに部分文字列を抽出する方法を示す簡単な例です。
>> s: "The score is 1:2 after 5 minutes"
>> if pos: find/tail s "score is " [print copy/part pos find pos " "]
1:2
少し練習すれば (このような実験にはコンソールが最適です)、単純な整数インデックスだけでなく、Rebol 言語でシリーズに完全に依存することがいかに簡単で効率的であるかがわかります。
さて、あなたの質問に対する私の見解は次のとおりです。
find
上記のように、シリーズと機能を適切に使用するだけで、魔法は必要ありません。
赤はそれを変えるつもりはありません。系列は、Rebol 言語をシンプルかつ強力にする基礎です。
change
ただし、長い文字列を操作するための置換が多数ある場合、元の文字列を変更する代わりに新しい文字列を再構築すると、置換文字列がないときにメモリチャンクを移動することを回避できるため、パフォーマンスが向上することがよくあります。交換する部品と同じサイズ。