Проверьте, равны ли два списка по типу 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()))