Фильтрация двух списков путем сравнения всех элементов друг с другом с помощью numpy или tabular - PullRequest
0 голосов
/ 26 мая 2011

У меня есть два списка кортежей, где кортежи в каждом списке уникальны.списки имеют следующий формат:

[('col1', 'col2', 'col3', 'col4'), ...]

Я использую вложенный цикл, чтобы найти элементы из обоих списков, которые имеют одинаковые значения для данных cols, col2 и col3

temp1 = set([])
temp2 = set([])
for item1 in list1:
    for item2 in list2:
        if item1['col2'] == item2['col2'] and \
            item1['col3'] == item2['col3']:
            temp1.add(item1)
            temp2.add(item2)

просто работает.но это занимает много минут, когда в списках десятки тысяч элементов.

Используя таблицу, я могу отфильтровать list1 agianst col2, col3 одного элемента для list2, как показано ниже:

list1 = tb.tabular(records=[...], names=['col1','col2','col3','col4'])
...

for (col1, col2, col3, col4) in list2:
    list1[(list1['col2'] == col2) & (list1['col3'] == col3)]    

, который явно "делает это неправильно" и намного медленнее, чем первый.

как я могу эффективно проверить элементы списка кортежей по всем элементам другого, используя numy или tabular?

спасибо

Ответы [ 3 ]

1 голос
/ 27 мая 2011

"как я могу эффективно проверять элементы списка кортежей по всем элементам другого, используя numpy или tabular"

Ну, у меня нет опыта работы с tabular и очень мало с numpy, поэтому я могуне дать вам точное «консервированное» решение.Но я думаю, что могу указать вам правильное направление.Если list1 имеет длину X, а list2 имеет длину Y, вы делаете проверки X * Y ... в то время как для выполнения проверок X + Y вам требуется только * .

Вы должны сделать что-то вроде следующего (я собираюсь притвориться, что это списки обычных кортежей Python - не табличных записей - я уверен, что вы можете внести необходимые корректировки):

common = {}
for item in list1:
    key = (item[1], item[2])
    if key in common:
        common[key].append(item)
    else:
        common[key] = [item]

first_group = []
second_group = []
for item in list2:
    key = (item[1], item[2])
    if key in common:
        first_group.extend(common[key])
        second_group.append(item)

temp1 = set(first_group)
temp2 = set(second_group)
1 голос
/ 26 мая 2011

Попробуйте:

temp1 = set([])
temp2 = set([])

dict1 = dict()
dict2 = dict()

for key, value in zip([tuple(l[1:3]) for l in list1], list1):
    dict1.setdefault(key, list()).append(value)

for key, value in zip([tuple(l[1:3]) for l in list2], list2):
    dict2.setdefault(key, list()).append(value)

for key in dict1:
    if key in dict2:
        temp1.update(dict1[key])
        temp2.update(dict2[key])

Грязный, но должен работать.

0 голосов
/ 27 мая 2011

Я бы создал подкласс кортежа, который имеет специальные __eq__ и __hash__ методы:

>>> class SpecialTuple(tuple):
...     def __eq__(self, t):
...             return self[1] == t[1] and self[2] == t[2]
...     def __hash__(self):
...             return hash((self[1], self[2]))
... 

Он сравнивает col1 и col2 и говорит, что кортеж равен при условии, что столбцы идентичны.

Тогда фильтрация просто использует пересечение set на этих специальных кортежах:

>>> list1 = [ (0, 1, 2, 0), (0, 3, 4, 0), (1, 2, 3, 12) ]
>>> list2 = [ (0, 1, 1, 0), (0, 3, 9, 9), (42, 2, 3, 12) ]
>>> set(map(SpecialTuple, list1)) & set(map(SpecialTuple, list2))
set([(42, 2, 3, 12)])

Я не знаю, как быстро. Скажи мне. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...