Pythonic способ сравнить многократные элементы в списке словарей

У меня есть список словарей в <�сильном> Пайтоне . У каждого элемента списка есть тип ключ с типом элемента. Что-то вроде этого:

e1 = {"type": 1, "value": 23.1}
e2 = {"type": 1, "value": 21.1}
e3 = {"type": 2, "value": -10.1}
e4 = {"type": 1, "value": -2.59}
l = [e1, e2, e3, e4]

Я хотел бы знать, имеют ли все элементы в списке l тот же самый тип .

У меня есть это:

def same_type(l):
    return l[0].type == l[1].type == l[2].type == l[3].type

Принятие списка всегда будет тем же самым размером, есть ли больше pythonic способа сделать это?

2
nl ja de
не только все ответы, но и мне нравитесь вы вопрос также...
добавлено автор Grijesh Chauhan, источник

3 ответы

Первая вещь, которая приходит в мою голову:

all(e['type'] == L[0]['type'] for e in L)

Длина набора типов:

len(set(e['type'] for e in L)) == 1

более эффективно, чем все с генератором, но не со списком:

>>> %timeit all(e['type'] == l[0]['type'] for e in l)
1000000 loops, best of 3: 784 ns per loop

>>> %timeit len(set(e['type'] for e in l)) == 1
1000000 loops, best of 3: 676 ns per loop

>>> %timeit all([e['type'] == l[0]['type'] for e in l])
1000000 loops, best of 3: 602 ns per loop

С припрятавшим про запас l [0] ['тип'] :

>>> t1 = l[0]['type']
>>> %timeit all([e['type'] == t1 for e in l])
1000000 loops, best of 3: 447 ns per loop

>>> %timeit all(e['type'] == t1 for e in l)
1000000 loops, best of 3: 655 ns per loop

set with a list-comp is even slower then with a genexpr:

>>> %timeit len(set([gettype(e) for e in l])) == 1
1000000 loops, best of 3: 735 ns per loop

 

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

>>> %timeit [e['type'] for e in l].count(t1) == len(l)
1000000 loops, best of 3: 421 ns per loop

 

Другой редактирует: по-видимому, самый прямой метод является самым быстрым:

In [31]: def same_type(L):
   ....:     t1 = L[0]['type']
   ....:     for e in L:
   ....:         if e['type'] != t1:
   ....:             return False
   ....:     return True
   ....:

In [32]: %timeit same_type(l)
1000000 loops, best of 3: 352 ns per loop

Лонг ввел с тем же самым типом (не срывающий)

In [47]: l = [{'type': 1} for _ in range(1000)]

In [48]: %timeit same_type(l)
10000 loops, best of 3: 37.6 us per loop

In [49]: %timeit  all(e['type'] == l[0]['type'] for e in l)
10000 loops, best of 3: 112 us per loop

In [50]: %timeit all([e['type'] == l[0]['type'] for e in l])
10000 loops, best of 3: 103 us per loop

In [51]: %timeit len(set(e['type'] for e in l)) == 1
10000 loops, best of 3: 63.3 us per loop

Лонг ввел с различными типами (короткое замыкание сразу же)

In [40]: l = [{'type': x} for x in range(1000)]

In [43]: %timeit same_type(l)
1000000 loops, best of 3: 337 ns per loop

In [44]: %timeit  all(e['type'] == l[0]['type'] for e in l)
1000000 loops, best of 3: 656 ns per loop

In [45]: %timeit all([e['type'] == l[0]['type'] for e in l])
10000 loops, best of 3: 99.4 us per loop

In [46]: %timeit len(set(e['type'] for e in l)) == 1
10000 loops, best of 3: 68.6 us per loop
8
добавлено
Будьте очень осторожны со своим временем здесь. все с генератором собьют список, если вы будете введены, который хорош для срывания. Кроме того, вы haven' t попробованный набор с аккомпанементом списка, который может (или не может) добиваться большего успеха, чем набор с genexp.
добавлено автор mgilson, источник
Что является вашим испытательным входом; время между двумя подходами зависит от входного размера и распределения второго типа (если есть).
добавлено автор Martijn Pieters, источник
По-видимому, закодированный рукой , все являются самыми эффективными.
добавлено автор Pavel Anossov, источник
Мой испытательный вход от вопроса. I' ll пробуют некоторые длинные списки и без различных типов.
добавлено автор Pavel Anossov, источник
Я думаю that' s предполагаемый быть L [0] [' type'] ?
добавлено автор Stjepan Bakrac, источник

Используйте набор() , чтобы собрать все типы, затем проверьте, является ли это длина 1:

def same_type(L):
    if not L: return True  # empty list case
    return len(set(d['type'] for d in L)) == 1

Это должно просмотреть все элементы. Вы могли также сравнить с <�ними> сначала элемент, в котором пункте только необходимо проверить достаточно, чтобы найти то, которое не соответствует:

def same_type(L):
    if not L: return True  # empty list case
    t = L[0]['type']
    return all(t == d['type'] for d in L)

Для меньших вводит набор() , подход быстрее, но для больше вводит вторую форму, может сбить набор() подход, если вероятность того, чтобы там быть вторым типом во входе достаточно большая.

5
добавлено
ошеломите... довольно умный. это было бы быстрее, чем другие два ответа (которые являются в основном тем же самым...),
добавлено автор Pablo Santa Cruz, источник
Привет Martijn! почему делают вы используете l [1:] ? где как Павел просто пишут в L) в его все выражение, он don' t разрезание использования.
добавлено автор Grijesh Chauhan, источник
@StevenRumbalski ahaa steven.. очень положительная сторона I' m немного удивленный!
добавлено автор Grijesh Chauhan, источник
@PabloSantaCruz: Я ожидаю все() , чтобы быть быстрее.
добавлено автор Martijn Pieters, источник
@GrijeshChauhan: ^
добавлено автор Martijn Pieters, источник
@GrijeshChauhan: Поскольку для первый элемент там не смысл в тестировании, если тип - то же самое.
добавлено автор Martijn Pieters, источник
@StevenRumbalski: Удаленный часть в целом теперь, даже используя проход() </ код> только замедляет вещи.
добавлено автор Martijn Pieters, источник
@StevenRumbalski: Верный; переключенный на использование iterator вместо этого.
добавлено автор Martijn Pieters, источник
См. мой ответ для тестов.
добавлено автор Pavel Anossov, источник
@GrijeshChauhan: Я предполагаю it' s один меньше теста, но я подозреваю, что он терпит неудачу, копируя большую часть списка.
добавлено автор Steven Rumbalski, источник
Если бы d большой, и работа действительно имеет значение, вы хотели бы припрятать l [0] про запас [' type'] .
добавлено автор Steven Rumbalski, источник

Работы для любой длины по местному стандартному времени :

def same_type(lst):
    return all(d['type'] == lst[0]['type'] for d in lst[1:])

выдерживая сравнение с len (набор (...)) == 1 это быстрее, потому что это останавливается, как только различное тип найдено.

4
добавлено
Python
Python
7 654 участник(ов)

Уютный чат для профессионалов, занимающихся поиском питоньих мудростей. Как не получить бан: https://t.me/ru_python/577926

Python beginners
Python beginners
4 449 участник(ов)

Вопросы про Python для чайников. Cпам и троллинг неприемлем. Не злоупотребляйте стикерами. Частозадаваемые вопросы: https://github.com/ru-python-beginners/faq/blob/master/README.md Статистика тут: https://grstats.me/chat/x4qym2k5uvfkr3al6at7

pro.python
pro.python
1 090 участник(ов)

Сообщество разработчиков под Python Создатель: @rodgelius

Rude Python
Rude Python
971 участник(ов)

Python без „девочек”, здесь матерятся и унижают Django. Not gay friendly. Правила: t.me/rudepython/114107 @rudepython | t.me/rudepython

rupython
rupython
509 участник(ов)

Группа создана с целью оперативного получения ответов на возникающие вопросы по разработке на яп python, смежные темы, а также человеческого общения. Приветствую!

Python-programming
Python-programming
266 участник(ов)

Чат группы вконтакте https://vk.com/python_community