Напечатать разные выходные значения, соответствующие дублирующемуся вводу в таблице?

Например, TableA:

     ID1    ID2   
     123    abc
     123    def
     123    ghi
     123    jkl
     123    mno
     456    abc
     456    jkl

Я хочу выполнить поиск строки для 123 и вернуть все соответствующие значения.

    pp = Cases[#, x_List /; 
     MemberQ[x, y_String /; 
       StringMatchQ[y, ToString@p, IgnoreCase -> True]], {1}] &@TableA

    {f4@"ID2", f4@pp[[2]]}

Выше p является вводом или 123. Это возвращает только одно значение для ID2. Как получить все значения для ID2?


person Rose    schedule 03.08.2011    source источник


Ответы (5)


В дополнение к другим решениям, я хотел бы исследовать высокопроизводительную сторону этой проблемы, то есть случай, когда таблица большая, и нужно выполнять много запросов. Очевидно, что в таком случае некоторая предварительная обработка может сэкономить много времени выполнения. Я хотел бы показать довольно неясное, но элегантное решение 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
comment
Я не понимаю, как это неясно, но, возможно, это только потому, что именно так я бы это и сделал. +1 - person Mr.Wizard; 14.08.2011
comment
@Mr.Wizard Для меня интересной частью было то, что, хотя Dispatch хеширует правила так, что только первый с идентичным l.h.s. fires (по крайней мере, я так об этом думал), он по-прежнему корректно работает с ReplaceList, который пробует все правила по списку, а также без снижения производительности. Я назвал его неясным, потому что и ReplaceList, и Dispatch обычно не так часто используются, а здесь у нас есть их комбинация. - person Leonid Shifrin; 14.08.2011
comment
Возможно, я недооценил сложность. У меня нет компьютерного образования, поэтому я обычно не думаю о том, как что-то (Dispatch) работает, а только о том, что оно, по-видимому, делает. Я действительно не рассматривал подробно, как работает Dispatch, только то, что он, по-видимому, оптимизирует список правил. Ожидали ли вы, что, среди прочего, Dispatch внутренне исключит правила два и три в: Dispatch @ {1 -> x, 1 -> y, 1 -> z} ? - person Mr.Wizard; 14.08.2011
comment
@Mr.Wizard Да, я думал, что это может быть возможный сценарий. Я не знаю точно, как реализовано Dispatch, но вот что говорится в документах: ... Такие правила, как a[1]->a1 и a[2]->a2, которые не могут применяться одновременно, не требуют явного сканирования обоих. Dispatch генерирует диспетчерскую таблицу, в которой используются хэш-коды, чтобы указать, какие наборы правил необходимо сканировать для конкретного входного выражения. ... . Так как я никогда раньше не видел комбинации ReplaceList и Dispatch в работе, я не был уверен. Кстати, у меня также нет компьютерного образования, чего мне сейчас очень не хватает. - person Leonid Shifrin; 14.08.2011

Кажется, что во всех ответах отсутствует функция, которая почти специально предназначена для подобных ситуаций, а именно Выберите. Pickвозвращает те элементы списка, для которых соответствующие элементы в секунду имеют значение True. Существует даже формат (который я буду использовать), который имеет третий аргумент, шаблон, которому должны соответствовать элементы второго списка.

list1 = {"ID1", "123", "123", "123", "123", "123", "456", "456"};
list2 = {"ID2", "abc", "def", "ghi", "jkl", "mno", "abc", "jkl"};

Pick[list2, list1, "123"]

==> {"abc", "def", "ghi", "jkl", "mno"}
person Sjoerd C. de Vries    schedule 04.08.2011

lis = {{"ID1", "ID2"},
  {"123", "abc"},
  {"123", "def"},
  {"123", "ghi"},
  {"123", "jkl"},
  {"123", "mno"},
  {"456", "abc"},
  {"456", "jkl"}}

(result = Cases[lis, {x_, y_} /; StringMatchQ[x, "123"] :> {x,y}]) // TableForm

введите здесь описание изображения

Если просто хотите RHS, то

Cases[lis, {x_, y_} /; StringMatchQ[x, "123"] :> y] // TableForm

введите здесь описание изображения

person Nasser    schedule 03.08.2011
comment
Вы можете упростить выражения до Cases[lis, {"123", _}] и Cases[lis, {"123", v_} :> v]. - person WReach; 04.08.2011

Этот?

Last@Transpose[Cases[tableA, {ToString@p, _}]]

(поскольку я не могу просто вырезать и вставить tableA из вашего вопроса в том виде, в котором он отформатирован, я не пробовал).

person acl    schedule 03.08.2011

TableA[[#[[1]], 2]] & /@ Position[TableA, 123]

person Cassini    schedule 04.08.2011