2010-05-14 4 views
120

В Python, какая структура данных более эффективна/ускорена? Предполагая, что этот порядок не важен для меня, и я все равно проверял бы дубликаты, является ли Python медленнее, чем список Python?Python Sets vs Lists

ответ

143

Это зависит от того, что вы собираетесь с ним делать.

Установки значительно быстрее, когда дело доходит до определения того, присутствует ли объект в наборе (как в x in s), но медленнее, чем списки, когда дело доходит до итерации по их содержимому.

Вы можете использовать timeit module, чтобы узнать, что быстрее для вашей ситуации.

+1

По вашему вопросу: «Наборы значительно быстрее», какова основная реализация, которая делает ее быстрее? – overexchange

+7

@overexchange хеш-таблицы http://stackoverflow.com/a/3949350/125507 – endolith

+1

https://en.wikipedia.org/wiki/Hash_table –

102

Если вы хотите сохранить некоторые значения, которые вы будете итерировать, конструкции списка Python немного быстрее. Однако, если вы будете хранить (уникальные) значения, чтобы проверить их существование, то наборы значительно быстрее.

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

Итерация

>>> def iter_test(iterable): 
...  for i in iterable: 
...   pass 
... 
>>> from timeit import timeit 
>>> timeit(
...  "iter_test(iterable)", 
...  setup="from __main__ import iter_test; iterable = set(range(10000))", 
...  number=100000) 
12.666952133178711 
>>> timeit(
...  "iter_test(iterable)", 
...  setup="from __main__ import iter_test; iterable = list(range(10000))", 
...  number=100000) 
9.917098999023438 
>>> timeit(
...  "iter_test(iterable)", 
...  setup="from __main__ import iter_test; iterable = tuple(range(10000))", 
...  number=100000) 
9.865639209747314 

Определить, если объект присутствует

>>> def in_test(iterable): 
...  for i in range(1000): 
...   if i in iterable: 
...    pass 
... 
>>> from timeit import timeit 
>>> timeit(
...  "in_test(iterable)", 
...  setup="from __main__ import in_test; iterable = set(range(1000))", 
...  number=10000) 
0.5591847896575928 
>>> timeit(
...  "in_test(iterable)", 
...  setup="from __main__ import in_test; iterable = list(range(1000))", 
...  number=10000) 
50.18339991569519 
>>> timeit(
...  "in_test(iterable)", 
...  setup="from __main__ import in_test; iterable = tuple(range(1000))", 
...  number=10000) 
51.597304821014404 
+3

Я обнаружил, что (Инициализационный набор -> 5.5300979614257812) (Инициализирующий список -> 1.8846848011016846) (Инициализация кортежа -> 1.8730108737945557) Элементы размером 10 000 на моем ядре i5 с ядром i5 с 12 ГБ оперативной памяти. Это также следует учитывать. – ThePracticalOne

+3

Я обновил код, чтобы удалить создание объекта сейчас. Фаза установки циклов timeit вызывается только один раз (https://docs.python.org/2/library/timeit.html#timeit.Timer.timeit). –

8

производительности Список:

>>> import timeit 
>>> timeit.timeit(stmt='10**6 in a', setup='a = range(10**6)', number=100000) 
0.008128150348026608 

производительность Set:

>>> timeit.timeit(stmt='10**6 in a', setup='a = set(range(10**6))', number=100000) 
0.005674857488571661 

Вы можете рассмотреть кортежей, как они похожи на списки, но не могут быть изменены. Они занимают немного меньше памяти и быстрее доступны. Они не такие гибкие, но эффективнее списков. Их нормальное использование - это словарные ключи.

Наборы также представляют собой структуры последовательности, но с двумя отличиями от списков и кортежей. Хотя у наборов есть порядок, этот порядок произволен, а не под контролем программиста. Второе отличие состоит в том, что элементы в наборе должны быть уникальными.

set по определению. [python | wiki].

>>> x = set([1, 1, 2, 2, 3, 3]) 
>>> x 
{1, 2, 3} 
+4

Прежде всего, вы должны обновить ссылку на встроенный тип 'set' (http://docs.python.org/2/library/stdtypes.html#set), а не устаревшую библиотеку' sets'. Во-вторых, «Наборы также являются структурами последовательностей», прочитайте следующее из встроенной ссылки типа: «Будучи неупорядоченной коллекцией, наборы не записывают позицию элемента или порядок вставки. Соответственно, наборы не поддерживают индексирование, нарезку или другое похожее на последовательность ». – Seaux

3

Set выигрывает из-за рядом момент «содержит» проверки: https://en.wikipedia.org/wiki/Hash_table

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

Набор реализация: https://en.wikipedia.org/wiki/Hash_table, не перебирать в списке, но находит элемент путем вычисления хэш из ключа, так это зависит от характера ключевых элементов и хэш-функции. Подобно тому, что используется для dict.Я подозреваю, что list может быть быстрее, если у вас очень мало элементов (< 5), чем больше элемент, тем лучше будет set для проверки наличия. Он также быстро добавляет и удаляет элементы.

ПРИМЕЧАНИЕ: Если list уже отсортирован, поиск в list может быть довольно быстро, но и для обычных случаев set быстрее и проще для проверки содержит.