Проверьте, равны ли два списка по типу Python
Я хочу проверить, имеют ли два списка один и тот же тип элементов для каждого индекса. Например, если у меня есть
y = [3, "a"]
x = [5, "b"]
z = ["b", 5]
проверка должна быть True
для x
и y
.
Проверка должна быть False
для y
и z
, потому что типы элементов в одинаковых положениях не равны.
Ответы
Ответ 1
Просто map
элементы к их type
и сравните их:
>>> x = [5, "b"]
>>> y = [3, "a"]
>>> z = ["b", 5]
>>> map(type, x) == map(type, y)
True
>>> map(type, x) == map(type, z)
False
Для Python 3 вам также нужно будет превратить генераторы map
в соответствующие списки, либо используя функцию list
или с выражением :
>>> list(map(type, x)) == list(map(type, y))
True
>>> [type(i) for i in x] == [type(i) for i in z]
False
Я сделал некоторый анализ времени, сравнив приведенное выше решение с @timgeb, используя all
и izip
, и входы с первым несогласованным типом в разных положениях. Как и ожидалось, время, затраченное на решение map
, практически одинаково для каждого входа, тогда как решение all
+ izip
может быть очень быстрым или занимать в три раза больше, в зависимости от положения первой разности.
In [52]: x = [1] * 1000 + ["s"] * 1000
In [53]: y = [2] * 1000 + ["t"] * 1000 # same types as x
In [54]: z = ["u"] * 1000 + [3] * 1000 # difference at first element
In [55]: u = [4] * 2000 # difference after first half
In [56]: %timeit map(type, x) == map(type, y)
10000 loops, best of 3: 129 µs per loop
In [58]: %timeit all(type(i) == type(j) for i, j in izip(x, y))
1000 loops, best of 3: 342 µs per loop
In [59]: %timeit all(type(i) == type(j) for i, j in izip(x, z))
1000000 loops, best of 3: 748 ns per loop
In [60]: %timeit all(type(i) == type(j) for i, j in izip(x, u))
10000 loops, best of 3: 174 µs per loop
Ответ 2
ленивая оценка с помощью all
:
>>> from itertools import izip
>>> all(type(a) == type(b) for a,b in izip(x,y))
True
Используйте обычный zip
в Python 3, он уже возвращает генератор.
Если списки могут иметь разную длину, просто проверьте длину вверх. Проверка длины - очень быстрая операция O (1):
>>> len(x) == len(y) and all(type(a) == type(b) for a,b in izip(x,y))
True
>>> x = [5,"b",'foo']
>>> len(x) == len(y) and all(type(a) == type(b) for a,b in izip(x,y))
False
and
будет оценена по короткому замыканию, что означает, что all
даже не будет вызываться, если длины отличаются.
Ответ 3
Другой вариант с lambda:
>>> x = [5, "b"]
>>> y = [3, "a"]
>>> z = ["b", 5]
>>> g = lambda t: [type(i) for i in t]
>>> g(x) == g(y)
True
>>> g(x) == g(z)
False
Ответ 4
Это очень просто, когда вы используете выражение генератора:
are_equal = all(type(i) == type(j) for i, j in zip(x, y))
В этом примере x
и y
- это списки, которые вы проверяете. Если вы хотите что-то, что вы можете добавить:
lists = (x, y)
are_equal = all(len(set(type(j) for j in i)) == 1 for i in zip(*lists))
Таким образом, вы можете просто изменить lists
, и он все равно будет работать. Он работает, используя тот факт, что set
удаляет все дубликаты. Для каждого кортежа, возвращаемого zip()
, он создает набор типов каждого элемента и проверяет, одинаковы ли они, если длина набора равна 1.
Ответ 5
def equalTypes(list1, list2):
if len(list1) != len(list2):
return False
for index, item in enumerate(list1):
if type(item) != type(list2[index]):
return False
return True
Я просто перебираю список (проверьте, имеют ли они первую длину), а затем, когда некоторые типы не совпадают, я возвращаю False. В конце (без несоответствия) я возвращаю True.
Ответ 6
Вы можете сохранить ленивую оценку, используя operator.eq
с itertools
, которая в целом дает вам приличные средние значения без сохранения копий списков:
In [12]: from itertools import imap, starmap, izip
In [13]: %timeit map(type, x) == map(type, y)
10000 loops, best of 3: 182 µs per loop
In [14]: %timeit all(type(i) == type(j) for i, j in izip(x, u))
1000 loops, best of 3: 239 µs per loop
In [15]: timeit all(type(i) == type(j) for i, j in izip(x, z))
1000000 loops, best of 3: 1.02 µs per loop
In [16]: %timeit all(type(i) == type(j) for i, j in izip(x, u))
1000 loops, best of 3: 234 µs per loop
In [17]: timeit all(starmap(eq, izip(imap(type, x), imap(type, y))))
1000 loops, best of 3: 238 µs per loop
In [18]: timeit all(starmap(eq, izip(imap(type, x), imap(type, u))))
10000 loops, best of 3: 120 µs per loop
In [19]: timeit all(starmap(eq, izip(imap(type, x), imap(type, z))))
1000000 loops, best of 3: 901 ns per loop
Если списки имели разную длину, просто проверка длины сначала была бы самой простой и быстрой, но если бы вы включили ее в логику, вы могли бы использовать объект как fillvalue для itertools.izip_longest
:
all(starmap(eq, izip_longest(imap(type, x), imap(type, y), fillvalue=object()))