В дополнение к другим решениям я хотел бы исследовать высокопроизводительный угол этой проблемы, то есть случай, когда таблица велика, и нужно выполнить много запросов.Очевидно, что какая-то предварительная обработка может сэкономить много времени выполнения в таком случае.Я хотел бы показать довольно неясное, но элегантное решение 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.