#python #list
#python #Список
Вопрос:
У меня есть два списка списков:
ll1=[[17],[35,6],[47,58,86]]
ll2=[[19],[75,8],[17,58,86]]
Как я мог бы объединить их, возможно, в for
цикле, создав новый список списков ll3
и пропустив повторяющиеся значения?
Предполагаемый результат был бы: ll3=[[17,19],[35,6,75,8],[47,58,86]]
Что равносильно объединению двух списков списков вместе, а затем удалению повторяющихся значений.
Комментарии:
1. вы пытаетесь избежать ЛЮБОГО значения, которое было в любом из предыдущих списков во время слияния?
2. всегда ли списки имеют одинаковый размер??
3. избавление от повторяющихся значений обычно означает, что вы все еще сохраняете одно из значений, вы действительно имеете в виду, что в третьем примере не должно быть 58 и 86?
4. Это не имеет смысла, потому что вы избавляетесь от 58, но сохраняете 17.
5. Возможно, было бы хорошей идеей дать обзор того, что вы пытаетесь сделать. Я подозреваю, что могут быть более эффективные способы выполнить некоторые из шагов, которые вы выполняете. Если вы дадите нам общую картину, мы сможем гарантировать, что мы не пытаемся решить проблему XY .
Ответ №1:
Предыдущие ответы, похоже, не соответствуют вашему требованию о том, что списки могут быть разных размеров.
В моем решении используются set
пересечения и объединения. Примечание. Я использую Python2, измените zip_longest
на izip_longest
.
ll1=[[17],[35,6],[47,58,86]]
ll2=[[19],[75,8],[17,58,86]]
from itertools import zip_longest
ll3 = []
seen = set()
for a, b in zip_longest(ll1, ll2, fillvalue=[]):
new = (set(a) | set(b)) - seen
ll3.append(list(new))
seen |= new
print (ll3)
Это выведет:
[[17, 19], [8, 75, 35, 6], [58, 86, 47]]
Это также сработает, если:
ll1=[[17],[35,6],[47,58,86],[5]]
ll2=[[19],[75,8],[17,58,86]]
возврат:
[[17, 19], [8, 75, 35, 6], [58, 86, 47], [5]]
Комментарии:
1. Почему я получаю
ImportError: cannot import name zip_longest
? Никогда раньше мне это не приходило в голову. Используя Python 2.7.11, 32-разрядный2. @CF84 если вы используете Python2, измените имя на
izip_longest
при импорте и вfor
цикле3. Извините, я допустил небольшую ошибку. Предполагаемый результат должен включать
58
и86
, которые я ошибочно пропустил. Проверьте мою правку и, опять же, приношу извинения.4. @CF84 Я просто немного почистил операции с разделением по битам: теперь это еще короче.
5. @CF84 хорошо, к счастью, это легко исправить: просто измените
^
на|
(я отредактировал соответствующим образом)
Ответ №2:
seen = set()
res = []
for a, b in zip(l1, l2):
subres = []
for item in a:
seen.add(item)
if item not in b and item not in seen:
subres.append(item)
for item in b:
seen.add(item)
if item not in a and item not in seen:
subres.append(item)
res.append(subres)
Комментарии:
1. ха, практически одно и то же решение примерно в одно и то же время
2. Рассмотрите возможность использования
set.symmetric_difference
3. @PM2Ring Я хотел избежать использования
set
s дляa
иb
в случае, если порядок имеет значение.4. Исходя из предыдущего вопроса OP, я почти уверен, что порядок в подсписке не имеет значения. Но неплохо бы получить разъяснения по подобным вопросам в комментариях к вопросу.
Ответ №3:
Для того, что, как вам кажется, вы ищете, я бы сохранил набор предыдущих значений.
old_values = {}
ll3 = []
for list_a, list_b in zip(ll1,ll2):
temp_list = []
for item in list_a:
if item in old_values or item in list_b:
pass
else:
temp_list.append(item)
old_values.add(item)
for item in list_b:
if item in old_values or item in list_a:
pass
else:
temp_list.append(item)
old_values.add(item)
ll3.append(temp_list)
Комментарии:
1. и вы могли бы изменить мои условия, чтобы они соответствовали ответу @PatrickHaugh. Его немного чище.
Ответ №4:
В общем случае — предполагая, что порядок элементов в результирующих вложенных списках не важен и 2 списка имеют одинаковую длину, вы можете использовать zip и set
ll3 = [set(l1 l2) - set(l1).intersection(l2) for l1, l2 in zip(ll1, ll2)]
seen = set()
for idx, elem in enumerate(ll3):
ll3[idx] = list(elem - seen)
seen.update(elem)
Комментарии:
1. Это не пропускает повторяющееся значение, но вместо этого включает одну копию в результат
2. @volcano это не сразу видно из вопроса, но OP также хочет исключить предыдущие увиденные значения (в данном случае вторые 17).
3. @brianpck, спасибо за разъяснение, исправлено, что