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