Я хочу добавить значение кортежа в кортеж, если этот кортеж [0: 2] повторяется, как показано ниже: - PullRequest
0 голосов
/ 18 ноября 2018

Здесь у меня есть список

some_list = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')]

. Предположим, 'A','B' находится в ('A','B','IP1','N1'),('A','B','IP3','N3'), тогда нам нужно объединить оба кортежа и создать один кортеж и заменить ('A','B','IP1','N1'),('A','B','IP3','N3') на ('A','B','IP1','N1','IP3','N3') в * 1008.*

Результат:

some_list = [('A','B','IP1','N1','IP3','N3'), ('B','C','IP2','N2','IP3','N3'), ]

должен прийти, но убедитесь, что вместо 'A', 'B', 'C', ... что бы это ни было, не всегда будет одинаковым

Можете ли вы помочь мне с этим?

Ответы [ 3 ]

0 голосов
/ 18 ноября 2018

Вы также можете использовать itertools.groupby(), чтобы сгруппировать кортежи по первым двум элементам, а затем объединить оставшуюся часть кортежа в конце со сглаживанием:

from itertools import groupby
from itertools import chain
from pprint import pprint


some_list = [
    ("A", "B", "IP1", "N1"),
    ("A", "B", "IP3", "N3"),
    ("B", "C", "IP2", "N2"),
    ("B", "C", "IP3", "N3"),
    ("D", "F", "IP4", "N4"),
]

# key -> first two, rest -> everything after first two
key, rest = lambda x: x[:2], lambda x: x[2:]

pprint(
    [
        list(chain.from_iterable((k, *tuple(map(rest, g)))))
        for k, g in groupby(sorted(some_list, key=key), key=key)
    ]
)

, что даетследующее:

[['A', 'B', 'IP1', 'N1', 'IP3', 'N3'],
 ['B', 'C', 'IP2', 'N2', 'IP3', 'N3'],
 ['D', 'F', 'IP4', 'N4']]

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

Кроме того, если ваш список кортежей всегда имеет длину 4, а ключ - это всегда первые два элемента, вы также можете использовать operater.itemgetter() для key и rest:

from operator import itemgetter
key, rest = itemgetter(0, 1), itemgetter(2, 3)

, который ищет первые два значения (0, 1) и два последних значения (2, 3) .

0 голосов
/ 18 ноября 2018

Вы также можете попробовать код ниже.

>>> def get_combined_items(tup1, tup2):
...     l = list(tup1)
...     for item in tup2:
...         if item not in l:
...             l.append(item)
...     return l
...
>>>
>>> if len(some_list) % 2 == 0: # even number of items
...     some_list = [tuple(get_combined_items(some_list[i], some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
... else:
...     last_item = some_list[-1] # save last item
...     some_list = [tuple(get_combined_items(some_list[i], some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
...     some_list = some_list + [last_item]
...
>>> some_list
[('A', 'B', 'IP1', 'N1', 'IP3', 'N3'), ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'), ('D', 'F', 'IP4', 'N4')]
>>>

А если вы хотите попробовать сторонний пакет, то установите ordered-set, используя pip install ordered-set.

"pip install упорядоченный набор

Вы можете проверить https://pypi.org/project/ordered-set/.

Примечание: Это просто для поддержания элементов в порядке после передачи объединенного кортежа в set().

>>> from ordered_set import OrderedSet
>>>
>>> some_list = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')]
>>>
>>> if len(some_list) % 2 == 0: # even number of items
...     some_list = [tuple(OrderedSet(some_list[i] + some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
... else:
...     last_item = some_list[-1] # save last item
...     some_list = [tuple(OrderedSet(some_list[i] + some_list[i + 1])) for i in range(0, len(some_list) - 1, 2)]
...     some_list = some_list + [last_item]
...
>>>
>>> some_list
[('A', 'B', 'IP1', 'N1', 'IP3', 'N3'), ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'), ('D', 'F', 'IP4', 'N4')]
>>>
0 голосов
/ 18 ноября 2018

В основном вам нужно создать ключ кортежа для ваших 2 значений и создать словарь по умолчанию с этим.

Расширение остальной части списка для каждого ключа и преобразование пары ключ / значение в список списков путем добавления ключа (в виде списка) к значению

как это:

import collections

some_list = [('A','B','IP1','N1'),('A','B','IP3','N3'),('B','C','IP2','N2'),('B','C','IP3','N3'),('D','F','IP4','N4')]

c = collections.defaultdict(list)
for k1,k2,*b in some_list:   # extended iterable unpacking allows this
    c[(k1,k2)].extend(b)  # add to existing list or create a new one

result = [a+tuple(b) for a,b in c.items()]

результат:

>>> result
[('D', 'F', 'IP4', 'N4'),
 ('B', 'C', 'IP2', 'N2', 'IP3', 'N3'),
 ('A', 'B', 'IP1', 'N1', 'IP3', 'N3')]

Часть for k1,k2,*b in some_list позволяет поместить 2 первых значения в отдельные переменные k1 и k2, а "остальные" - в список b. Эта функция недоступна в Python 2. Пользователи Python 2 могут заменить цикл более простым:

for a in some_list:
    c[tuple(a[:2])].extend(a[2:])  # add to existing list or create a new one

(эта проблема похожа на эту: Объединение кортежей с одним и тем же ключом для основной части, но предварительная / постобработка делает его другим)

...