Performance_Python получает объединение 2 списков кортежей в соответствии с 2 из 3 элементов кортежа - PullRequest
3 голосов
/ 18 ноября 2010

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

Я нашел много интересных подсказок в Интернете и особенно на этом сайте ообъединение списка.Однако мне не удалось применить это к моей проблеме.Моя цель - избавиться от кортежа, два последних элемента которого похожи на другой кортеж в списке.например:

list1=[[a,b,c],[d,e,f],[g,h,i]]
list2=[[b,b,c],[d,e,a],[k,h,i]]
the result should be:
final=[[a,b,c],[d,e,f],[g,h,i],[d,e,a]]

Сейчас я использую циклы и разрывы, но я надеюсь ускорить этот процесс.

вот как выглядит мой код (result и tempсписки, из которых я хочу получить объединение) на python2.6.

for k in xrange(len(temp)):
    u=0
    #index= next((j for j in xrange(lenres) if temp[k][1:3] == result[j][1:3]),None)
    for j in xrange(len(result)):
        if temp[k][1:3] == result[j][1:3]:
            u=1
            break
    if u==0:
    #if index is None:
        result.append([temp[k][0],temp[k][1],temp[k][2]])

Спасибо за вашу помощь

Herve

Ответы [ 2 ]

1 голос
/ 18 ноября 2010

Вот простое решение с использованием набора:

list1=[('a','b','c'),('d','e','f'),('g','h','i')]
list2=[('b','b','c'),('d','e','a'),('k','h','i')]

set1 = set([A[1:3] for A in list1])
final = list1 + [A for A in list2 if A[1:3] not in set1]

Однако, если ваши list1 и list2 на самом деле не состоят из кортежей, то вам придется поместить tuple () вокруг A [1: 3].

1 голос
/ 18 ноября 2010

Ниже приведена наша уникальная функция. Он принимает аргументы l (list) и f (function), возвращает список с удаленными дубликатами (в том же порядке). Дубликаты определяются следующим образом: b является дубликатом, если f (b) == f (a).

def uniques(l, f = lambda x: x):
    return [x for i, x in enumerate(l) if f(x) not in [f(y) for y in l[:i]]]

Мы определяем lastTwo следующим образом:

lastTwo = lambda x: x[-2:]

Для вашей проблемы мы используем его следующим образом:

>>> list1
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i')]
>>> list2
[('b', 'b', 'c'), ('d', 'e', 'a'), ('k', 'h', 'i')]
>>> uniques(list1+list2, lastTwo)
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('d', 'e', 'a')]

Если описанный вами вариант использования часто встречается, вы можете определить

def hervesMerge(l1, l2):
    return uniques(l1+l2, lambda x: x[-2:])

Идентичность - это наше значение по умолчанию f, но оно может быть любым (если оно определено для всех элементов списка, поскольку они могут быть любого типа).

f может быть суммой списка, нечетными элементами списка, простыми множителями целого числа, чем угодно. (Просто помните, что если у его инъективного нет смысла! Добавление с помощью константы, линейных функций и т. Д. Будет работать не иначе, как тождество bc его f (x) == f (y) w / x! = Y, который имеет значение)

>>> list1
[(1, 2, 3, 4), (2, 5), (6, 2, 2), (3, 4), (8, 3), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]
>>> uniques(list1, sum)
[(1, 2, 3, 4), (2, 5), (8, 3)]
>>> uniques(list1, lambda x: reduce(operator.mul, x))  #product
[(1, 2, 3, 4), (2, 5), (3, 4), (1, 1, 1, 1, 1, 1, 1, 1, 1, 1)]
>>> uniques([1,2,3,4,1,2]) #defaults to identity
[1, 2, 3, 4]

Вы, похоже, беспокоились о скорости, но мой ответ действительно был сосредоточен на краткости / гибкости без значительного (или какого-либо?) Улучшения скорости. Для больших списков, для которых важна скорость z, вы хотите воспользоваться проверками на хеширование и тем фактом, что списки list1 и list2 не имеют дубликатов

>>> s = frozenset(i[-2:] for i in list1)
>>> ans = list(list1) #copy list1
>>> for i in list2:
        if i[-2:] not in s: ans.append(i)
>>> ans
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('d', 'e', 'a')]

ИЛИ разрешая беспорядок

>>> d = dict()
>>> for i in list2 + list1:
        d[i[-2:]] = i
>>> d.values()
[('d', 'e', 'f'), ('a', 'b', 'c'), ('g', 'h', 'i'), ('d', 'e', 'a')]   

- Изменить -

Вы всегда должны быть в состоянии избежать непитонических циклов, как вы пишете в своем вопросе. Вот ваш точный код с измененными циклами:

for k in temp:
  u=0
  for j in result:
      if k[1:3] == j[1:3]:
          u=1
          break
  if u==0:
  #if index is None:
      result.append([k[0],k[1],k[2]])   // k

result и temp являются итеративными, и для любого итеративного вы можете поместить его непосредственно в цикл for без eanges. Если по какой-то причине вам явно нужен индекс (это не тот случай, но у меня есть один выше), вы можете использовать перечисление.

...