Как найти разницу между двумя списками, состоящими из разных типов данных с помощью Python

#python #list #types

#python #Список #типы

Вопрос:

Описание:

Введите A:

 ([1, 2, 3, 4, 5, 6, 7, 8], [1, 3, 4, 5, 6, 7, 8]) ➞ 2
 

Тип B:

 ([True, True, False, False, True], [False, True, False, True]) ➞ True
 

Введите C:

 (["Jane", "is", "pretty", "ugly"], ["Jane", "is", "pretty"]) ➞ "ugly"
 

Введите D:

 (["different", "types", "5", 5, [5], (5,)], ["5", "different", [5], "types", 5]) ➞ (5,)
 

Прогресс:
Для A / C я бы сначала превратил их в два набора, а затем использовал set.difference() или «-«, чтобы найти разницу. Однако этот метод не применяется к B, но я все равно могу использовать «Counter ()», чтобы получить повторяющиеся времена каждого элемента, а затем выяснить разницу.

Проблема: теперь я застрял с D. Я думаю, будь то «set.difference ()» или «-» или «Counter ()», они могут довольно хорошо работать со списками, состоящими из одного и того же типа данных, но D состоит из строки, целого числа, списка, кортежа, т. Е. Разных типов данных, так как иметь делос этим в Python?

Следующий шаг: для меня самый простой способ — найти функцию, которая может, по крайней мере, подсчитывать типы этих элементов в D, чтобы я мог сначала сравнить их, прежде чем перейти к значениям этих элементов. Это хороший способ?

Ответ №1:

Один из способов перебора — перебирать элементы во втором списке, удаляя элемент из первого списка:

 a = ["different", "types", "5", 5, [5], (5,)]
b = ["5", "different", [5], "types", 5]

a_copy = a.copy()
for x in b:
    a_copy.remove(x)
print(a_copy) # [(5,)]
 

Предполагается, что b это подсписок a (с точностью до перестановки).

Комментарии:

1. Какое совпадение, я тестирую его примерно 1 секунду назад

Ответ №2:

Основная проблема заключается в том, что элементы набора и ключи словаря (счетчик использует dict внутри) должны быть хешируемыми, но нет никакой гарантии, что элементы в двух заданных списках являются хешируемыми. В вашем примере D есть список [5] , который нельзя хэшировать, потому что он изменяемый.

Согласно документам Python:

Большинство неизменяемых встроенных объектов Python являются хешируемыми; изменяемые контейнеры (такие как списки или словари) — нет; неизменяемые контейнеры (такие как кортежи и замороженные наборы) являются хешируемыми, только если их элементы являются хешируемыми.

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

  • Если есть совпадение: удалите совпадение из второго списка.
  • Если совпадения нет, добавьте его в третий список, содержащий разницу в списке.
  • Сделайте копии списков заранее, используя .copy() , если их нужно сохранить.

В конце переместите все оставшиеся элементы из второго списка в третий список и верните его.

Этот алгоритм не очень эффективен: O (nm) время, если первый список имеет размер n, а второй список имеет размер m. Но это может быть необходимо, учитывая отсутствие предположений, которые мы можем сделать относительно ввода.


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

  • Вместо того, чтобы хранить элемент x в счетчике, мы сохраняем кортеж (type(x), x) .
  • Исключение составляет, если x является списком, и в этом случае мы сохраняем (type(x), tuple(x)) .
  • (5,) сохраняет как (<class 'tuple'>, (5,))
  • [5] сохраняет как (<class 'list'>, (5,))

Теперь вы можете просто сравнить счетчики, чтобы найти разницу. Это быстрее, чем решение методом перебора, но вам придется продолжать добавлять исключения, поскольку вы допускаете все больше и больше нехешируемых элементов во входных списках (например, set -> frozenset ). С помощью этого метода в какой-то момент вам придется установить некоторые ограничения на то, что могут содержать входные данные.