Удалить кортежи в многомерном списке, если они одинаковые - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть список кортежей, а именно:

[[[('p', 'u'), ('r', 'w')], [('t', 'q')]], [[('p', 'u'), ('r', 'w')], [('v', 'q')]], [[('p', 'u'), ('r', 'w')], [('t', 's')]], [[('p', 'u'), ('r', 'w')], [('v', 's')]], [[('p', 'w'), ('r', 'u')], [('t', 'q')]], [[('p', 'w'), ('r', 'u')], [('v', 'q')]], [[('p', 'w'), ('r', 'u')], [('t', 's')]], [[('p', 'w'), ('r', 'u')], [('v', 's')]], [[('r', 'u'), ('p', 'w')], [('t', 'q')]], [[('r', 'u'), ('p', 'w')], [('v', 'q')]], [[('r', 'u'), ('p', 'w')], [('t', 's')]], [[('r', 'u'), ('p', 'w')], [('v', 's')]], **[[('r', 'w'), ('p', 'u')], [('t', 'q')]]**, [[('r', 'w'), ('p', 'u')], [('v', 'q')]], [[('r', 'w'), ('p', 'u')], [('t', 's')]], [[('r', 'w'), ('p', 'u')], [('v', 's')]]]

Но теперь, например, элемент [[('p','u'),('r','w')], [('t','q')]]

такой же, как [[('r','w'),('p','u')], [('t','q')]], которые помечены fat в списке.

Таким образом, в списке у меня есть 16 элементов, где каждый элемент является двойным.

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

Так наивно, я пытался с

[[list(y) for y in set([tuple(set(x)) for x in doublegammas1])]]

Но здесьон говорит:

TypeError: unhashable type: 'list'

Итак, мой вопрос:

Как я могу расширить понимание списка, чтобы оно работало для более многомерного списка?

Ответы [ 2 ]

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

Списки не являются хэшируемыми, кортежи являются хэшируемыми. Затем вам нужно взять set из этих кортежей. Но внутри этих кортежей вы хотите игнорировать порядок. Но кортежи наборов не могут быть хэшируемыми, поэтому вместо них вам нужно использовать кортежи из frozenset объектов:

uniques = {tuple(map(frozenset, i)) for i in doublegammas1}

print(uniques)

{(frozenset({('p', 'w'), ('r', 'u')}), frozenset({('t', 'q')})),
 (frozenset({('p', 'w'), ('r', 'u')}), frozenset({('v', 'q')})),
 (frozenset({('p', 'w'), ('r', 'u')}), frozenset({('v', 's')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 's')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 'q')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 'q')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 's')})),
 (frozenset({('p', 'w'), ('r', 'u')}), frozenset({('t', 's')}))}

Затем вы можете применить это с помощью рецепта itertools unique_everseen , также доступного в сторонних библиотеках как toolz.unique или more_itertools.unique_everseen :

from more_itertools import unique_everseen

def uniquekey(x):
    return tuple(map(frozenset, x))

res = list(unique_everseen(doublegammas1, key=uniquekey))

print(res)

[[[('p', 'u'), ('r', 'w')], [('t', 'q')]],
 [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
 [[('p', 'u'), ('r', 'w')], [('t', 's')]],
 [[('p', 'u'), ('r', 'w')], [('v', 's')]],
 [[('p', 'w'), ('r', 'u')], [('t', 'q')]],
 [[('p', 'w'), ('r', 'u')], [('v', 'q')]],
 [[('p', 'w'), ('r', 'u')], [('t', 's')]],
 [[('p', 'w'), ('r', 'u')], [('v', 's')]]]

Входные данные

# input data
doublegammas1 = [[[('p', 'u'), ('r', 'w')], [('t', 'q')]],
                 [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
                 [[('p', 'u'), ('r', 'w')], [('t', 's')]],
                 [[('p', 'u'), ('r', 'w')], [('v', 's')]],
                 [[('p', 'w'), ('r', 'u')], [('t', 'q')]],
                 [[('p', 'w'), ('r', 'u')], [('v', 'q')]],
                 [[('p', 'w'), ('r', 'u')], [('t', 's')]],
                 [[('p', 'w'), ('r', 'u')], [('v', 's')]],
                 [[('r', 'u'), ('p', 'w')], [('t', 'q')]],
                 [[('r', 'u'), ('p', 'w')], [('v', 'q')]],
                 [[('r', 'u'), ('p', 'w')], [('t', 's')]],
                 [[('r', 'u'), ('p', 'w')], [('v', 's')]],
                 [[('r', 'w'), ('p', 'u')], [('t', 'q')]],
                 [[('r', 'w'), ('p', 'u')], [('v', 'q')]],
                 [[('r', 'w'), ('p', 'u')], [('t', 's')]],
                 [[('r', 'w'), ('p', 'u')], [('v', 's')]]]
0 голосов
/ 19 ноября 2018

Изменяемый объект (например, список или набор) не может быть членом набора. Вы можете использовать морозильник, который является неизменным.

main_list = [[[('p', 'u'), ('r', 'w')], [('t', 'q')]],
             [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
             [[('p', 'u'), ('r', 'w')], [('t', 's')]],
             [[('p', 'u'), ('r', 'w')], [('v', 's')]],
             [[('p', 'w'), ('r', 'u')], [('t', 'q')]],
             [[('p', 'w'), ('r', 'u')], [('v', 'q')]],
             [[('p', 'w'), ('r', 'u')], [('t', 's')]],
             [[('p', 'w'), ('r', 'u')], [('v', 's')]],
             [[('r', 'u'), ('p', 'w')], [('t', 'q')]],
             [[('r', 'u'), ('p', 'w')], [('v', 'q')]],
             [[('r', 'u'), ('p', 'w')], [('t', 's')]],
             [[('r', 'u'), ('p', 'w')], [('v', 's')]],
             [[('r', 'w'), ('p', 'u')], [('t', 'q')]],
             [[('r', 'w'), ('p', 'u')], [('v', 'q')]],
             [[('r', 'w'), ('p', 'u')], [('t', 's')]],
             [[('r', 'w'), ('p', 'u')], [('v', 's')]]]

main_set = set(tuple(frozenset(innermost_list) for innermost_list in sublist) for sublist in main_list)

from pprint import pprint
pprint(main_set)

Выход:

{(frozenset({('r', 'u'), ('p', 'w')}), frozenset({('t', 'q')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 'q')})),
 (frozenset({('r', 'u'), ('p', 'w')}), frozenset({('v', 'q')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 's')})),
 (frozenset({('r', 'u'), ('p', 'w')}), frozenset({('t', 's')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('v', 's')})),
 (frozenset({('r', 'u'), ('p', 'w')}), frozenset({('v', 's')})),
 (frozenset({('p', 'u'), ('r', 'w')}), frozenset({('t', 'q')}))}

Чтобы преобразовать обратно в исходную структуру вложенных списков:

new_list = [[list(frozen) for frozen in subtuple] for subtuple in main_set]
pprint(new_list)

Выход:

[[[('r', 'u'), ('p', 'w')], [('t', 'q')]],
 [[('p', 'u'), ('r', 'w')], [('v', 'q')]],
 [[('r', 'u'), ('p', 'w')], [('v', 'q')]],
 [[('p', 'u'), ('r', 'w')], [('t', 's')]],
 [[('r', 'u'), ('p', 'w')], [('t', 's')]],
 [[('p', 'u'), ('r', 'w')], [('v', 's')]],
 [[('r', 'u'), ('p', 'w')], [('v', 's')]],
 [[('p', 'u'), ('r', 'w')], [('t', 'q')]]]

UPDATE:

Решение, которое удаляет дублирующиеся элементы на месте из входных данных.

unique = []

for item in main_list[:]:
    frozen_item = frozenset(frozenset(innermost_list) for innermost_list in item)
    if frozen_item not in unique:
        unique.append(frozen_item)
    else:
        main_list.remove(item)
...