他のソリューションを補完するために、この問題のハイ パフォーマンス コーナー、つまり、テーブルが大きく、多くのクエリを実行する必要がある場合を調べたいと思います。明らかに、ある種の前処理は、そのような場合に多くの実行時間を節約できます。と の組み合わせに基づく、かなりあいまいですが IMO のエレガントなソリューションを示したいと思いDispatch
ますReplaceList
。説明用の小さな表を次に示します (元の質問に近づけるために、すべてのエントリに文字列を使用しています)。
makeTestTable[nids_, nelems_] :=
Flatten[Thread[{"ID" <> ToString@#,
ToString /@ Range[#, nelems + # - 1]}] & /@ Range[nids], 1]
In[57]:= (smallTable = makeTestTable[3,5])//InputForm
Out[57]//InputForm=
{{"ID1", "1"}, {"ID1", "2"}, {"ID1", "3"}, {"ID1", "4"}, {"ID1", "5"},
{"ID2", "2"}, {"ID2", "3"}, {"ID2", "4"}, {"ID2", "5"}, {"ID2", "6"},
{"ID3", "3"}, {"ID3", "4"}, {"ID3", "5"}, {"ID3", "6"}, {"ID3", "7"}}
前処理ステップはDispatch
、元のテーブルからルールの -ed テーブルを作成することで構成されます。
smallRules = Dispatch[Rule @@@ smallTable];
値を取得するコード (たとえば、"ID2" の場合) は次のとおりです。
In[59]:= ReplaceList["ID2", smallRules]
Out[59]= {"2", "3", "4", "5", "6"}
これは大したことではないように見えますが、より大きなテーブルに移りましょう。
In[60]:= Length[table = makeTestTable[1000,1000]]
Out[60]= 1000000
前処理ステップには確かに時間がかかります。
In[61]:= (rules = Dispatch[Rule @@@ table]); // Timing
Out[61]= {3.703, Null}
しかし、必要なのは一度だけです。これで、後続のすべてのクエリ (おそらく最初のクエリを除く) はほぼ瞬時に実行されます。
In[75]:= ReplaceList["ID520",rules]//Short//Timing
Out[75]= {0.,{520,521,522,523,524,525,<<988>>,1514,1515,1516,1517,1518,1519}}
一方、前処理を行わないアプローチでは、このテーブル サイズに対してかなりの時間がかかります。
In[76]:= Cases[table,{"ID520",_}][[All,2]]//Short//Timing
Out[76]= {0.188,{520,521,522,523,524,525,<<988>>,1514,1515,1516,1517,1518,1519}}
これは元の質問に対してやり過ぎかもしれないことを理解していますが、このようなタスクはかなり一般的です。たとえば、誰かがデータベースからインポートされた大規模なデータセットを Mathematica で直接調べたい場合などです。