次の(たとえば)データがあります
'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│a│b│c│a│b│a│
└─┴─┴─┴─┴─┴─┘
'a'
そして、すべてを数字に置き換えたい3
、および'b'
別の数字に置き換えて4
、元に戻す
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
どうやってやるの?
手伝ってくれてありがとう。
次の(たとえば)データがあります
'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│a│b│c│a│b│a│
└─┴─┴─┴─┴─┴─┘
'a'
そして、すべてを数字に置き換えたい3
、および'b'
別の数字に置き換えて4
、元に戻す
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
どうやってやるの?
手伝ってくれてありがとう。
それが(のような)文字列だった場合、次'abcaba'
の簡単な解決策がありrplc
ます:
'abcaba' rplc 'a';'3';'b';'4'
34c343
}
ボックス化されたデータのようにする必要がある場合(たとえば、「a」が文字やアトムよりも複雑なものを表す場合)、amend}
を使用できます。
L =: 'a';'b';'c';'a';'b';'a'
p =: I. (<'a') = L NB. positions of 'a' in L
0 3 5
(<'3') p } L NB. 'amend' "3" on those positions
上記をダイアドに入れる:
f =: 4 :'({.x) (I.({:x) = y) } y' NB. amend '{.x' in positions where '{:x' = y
('3';'a') f L
┌─┬─┬─┬─┬─┬─┐
│3│b│c│3│b│3│
└─┴─┴─┴─┴─┴─┘
より複雑な設定で使用できます。
]L =: (i.5);'abc';(i.3);'hello world';(<1;2)
┌─────────┬───┬─────┬───────────┬─────┐
│0 1 2 3 4│abc│0 1 2│hello world│┌─┬─┐│
│ │ │ │ ││1│2││
│ │ │ │ │└─┴─┘│
└─────────┴───┴─────┴───────────┴─────┘
((1;2);(i.3)) f L
┌─────────┬───┬─────┬───────────┬─────┐
│0 1 2 3 4│abc│┌─┬─┐│hello world│┌─┬─┐│
│ │ ││1│2││ ││1│2││
│ │ │└─┴─┘│ │└─┴─┘│
└─────────┴───┴─────┴───────────┴─────┘
ところで、{.y
の最初の項目ですy
。{:y
の最後の項目ですy
ツールボックスに入れることができる小さなユーティリティを次に示します。
tr =: dyad def '(y i.~ ({." 1 x),y) { ({:" 1 x) , y'
] MAP =: _2 ]\ 'a';3; 'b';4
+-+-+
|a|3|
+-+-+
|b|4|
+-+-+
MAP tr 'a';'b';'c';'a';'b';'a'
+-+-+-+-+-+-+
|3|4|c|3|4|3|
+-+-+-+-+-+-+
ユーティリティtr
は、2 つの引数 (ダイアド) を取る動詞です。右の引数はターゲットで、左の引数はマッピング テーブルです。テーブルには 2 つの列が必要であり、各行は 1 つのマッピングを表します。1 つの置換のみを行うには、2 つの項目のベクトルを使用できます (つまり、リストが 2 つの項目の長さである限り、2D テーブルではなく 1D リスト)。
テーブルはターゲットと同じデータ型でなければならないことに注意してください (つまり、ボックスを置き換える場合はボックスのテーブル、文字の場合は文字のテーブル、数字の場合は数字など)。
また、like-for-like マッピングを行っているため、マッピング テーブルのセルはターゲットのアイテムと同じ形状でなければならず、文字列置換などの形状シフトが必要なタスクには適していません。たとえば、動作し('pony';'horse') tr 'I want a pony for christmas'
ません (ただし、面白い'pony horse' tr&.;: 'I want a pony for christmas'
ことに、ここでは説明しませんが、動作します)。
あなたの質問に対する標準的な答えはありません。そうは言っても、翻訳を行うための非常に一般的なイディオムがあります ( tr
、またはマッピング 1:1 の意味で):
FROM =: ;: 'cat dog bird'
TO =: ;: 'tiger wolf pterodactyl'
input=: ;: 'cat bird dog bird bird cat'
(FROM i. input) { TO
+-----+-----------+----+-----------+-----------+-----+
|tiger|pterodactyl|wolf|pterodactyl|pterodactyl|tiger|
+-----+-----------+----+-----------+-----------+-----+
これを分解すると、プリミティブi.
はルックアップ関数であり、プリミティブ{
は選択関数です (ニーモニック:探している要素 i.
の * i * インデックスが得られます)。
しかし、上記の単純化された定式化は、文字通り入力内のすべてを置き換えたい場合にのみ適用され、FROM
合計であることが保証されます (つまり、入力の項目は にあるものに制限されますFROM
)。
これらの制約により、すべての文字を置き換えたい文字列の大文字と小文字の変換などのタスクに適した単純な定式化が行われ、文字の全宇宙が事前にわかっています (つまり、アルファベットは有限です)。
しかし、有限の宇宙がなければどうなるでしょうか? 認識されていないアイテムはどうすればよいですか? まあ、私たちが望むものは何でも。この柔軟性の必要性が、J に単一の翻訳機能がない理由です。代わりに、言語は、ニーズに固有のソリューションを作成するためのツールを提供します。
たとえば、上記のパターンの非常に一般的な拡張の 1 つは、(認識されないアイテムの) デフォルトで置換するという概念です。そして、はルックアップで見つからないアイテムi.
を返すように定義されているため、拡張は驚くほど単純です。置換リストを 1 アイテムだけ拡張するだけです。つまり、デフォルトを追加するだけです。1+#input
DEFAULT =: <'yeti'
input=: ;: 'cat bird dog horse bird monkey cat iguana'
(FROM i. input) { TO,DEFAULT
+-----+-----------+----+----+-----------+----+-----+----+
|tiger|pterodactyl|wolf|yeti|pterodactyl|yeti|tiger|yeti|
+-----+-----------+----+----+-----------+----+-----+----+
もちろん、これは可逆ではないという意味で破壊的です: 入力に関する情報を残しません。あなたの質問のように、何かを置き換える方法がわからない場合は、そのままにしておくのが最善の方法です。
繰り返しますが、この種の拡張は驚くほど単純で、一度見れば明らかです:入力を追加してルックアップ テーブルを拡張します。そうすれば、入力のすべての項目を確実に見つけることができます。置換も同様に単純です: input を追加して置換リストを拡張します。したがって、すべての不明なアイテムをそれ自体に置き換えることになります。
( (FROM,input) i. input) { TO,input
+-----+-----------+----+-----+-----------+------+-----+------+
|tiger|pterodactyl|wolf|horse|pterodactyl|monkey|tiger|iguana|
+-----+-----------+----+-----+-----------+------+-----+------+
これが で具現化された戦略tr
です。
ところで、 のようなユーティリティを書くときtr
、J プログラマーはしばしば N 次元のケースを考慮するでしょう。それが言語の精神だからです。現状でtr
は、2 次元のマッピング テーブルが必要です (偶然にも、便利な 2 つの項目の 1 次元リストを受け入れます)。しかし、キューブ内の平面やハイパーキューブ内のキューブなどを置き換えたい日が来るかもしれません (ビジネス インテリジェンス アプリケーションでは一般的です)。これらのケースが発生した場合に備えて、ユーティリティを拡張してこれらのケースをカバーしたいと思うかもしれません。
しかし、どのように?マッピング テーブルには少なくとも2 つのディメンションが必要です。1 つは複数の同時置換を保持するためのもので、もう 1 つは置換のルールを保持するためのものです (つまり、置換ごとに 1 つの「行」と、アイテムとその置換を識別するための 2 つの「列」)。 . ここで重要なのは、必要なのはそれだけです。を一般化するには、これらの次元の下にあるものは気にしないtr
と言うだけで十分です。単一文字の Nx2 テーブル、固定長文字列の Nx2 テーブル、線形代数の目的での行列の Nx2 テーブル、または ... 誰が気にしますか? 私たちの問題ではありません。コンテンツではなく、フレームのみを気にします。
tr
では、次のように言いましょう。
NB. Original
tr =: dyad def '(y i.~ ({." 1 x),y) { ({:" 1 x) , y'
NB. New, laissez-faire definition
tr =: dyad def '(y i.~ ({."_1 x),y) { ({:"_1 x) , y'
ご覧のとおり、大変な変更です;)。ややこしい: ランク演算子"
は、正または負の引数を取ることができます。正の引数を指定すると、動詞はその入力の内容をアドレス指定できますが、負の引数を指定すると、動詞はその入力のフレームをアドレス指定できます。ここで、"1
(正) は{.
の行に適用されx
、"_1
(負) は の「行」に適用されますx
。ここで、怖がらせ引用符の「行」は、たまたま 37 であっても、単に最初の次元に沿った項目を意味します。 -次元の超長方形。誰も気にしない?
さて、一人の男が気になります。の元の定義でtr
は、最も怠惰なプログラマーが('dog';'cat') tr ;: 'a dog makes the best pet'
代わりに書くことができ(,:'dog';'cat') tr ;: 'a dog makes the best pet'
ます。つまり、元のtr
(完全に偶然に) 単純なリストをマッピング テーブルとして許可していましたが、これはもちろん、抽象的で仮想的な意味でも Nx2 テーブルではありません (少なくとも2 つの次元がないため)。この利便性を維持したいのかもしれません。もしそうなら、ユーザーに代わって退化した引数を促進する必要があります:
tr =: dyad define
x=.,:^:(1=#@$) x
(y i.~ ({."_1 x),y) { ({:"_1 x) , y
)
結局、怠惰はプログラマーの第一の美徳です。
あなたが求めたことを達成するために私が考えることができる最も簡単な方法は次のとおりです。
(3;3;3;4;4) 0 3 5 1 4} 'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
ここに別のアプローチがあります
(<3) 0 3 5} (<4) 1 4} 'a';'b';'c';'a';'b';'a'
┌─┬─┬─┬─┬─┬─┐
│3│4│c│3│4│3│
└─┴─┴─┴─┴─┴─┘
仮説的に言えば、この種の表現を一般化したい場合や、別の表現が必要な場合があります。ここの他のポスターがそれを行う方法を指摘していると思います。. しかし、最も単純な形を見るだけでも面白いことがありますか?
ちなみに、上記のインデックスを取得した方法は次のとおりです(すべてではなく一部の無関係なものが削除されています)。
I. (<'a') = 'a';'b';'c';'a';'b';'a'
0 3 5
('a') =S:0 'a';'b';'c';'a';'b';'a'
1 0 0 1 0 1
('a') -:S:0 'a';'b';'c';'a';'b';'a'
1 0 0 1 0 1
I.('a') -:S:0 'a';'b';'c';'a';'b';'a'
0 3 5
I.('b') -:S:0 'a';'b';'c';'a';'b';'a'
1 4