В Python, какая структура данных является более эффективной / быстрой? Предполагая, что порядок не важен для меня, и я все равно буду проверять наличие дубликатов, является ли набор Python более медленным, чем список Python?
В Python, какая структура данных является более эффективной / быстрой? Предполагая, что порядок не важен для меня, и я все равно буду проверять наличие дубликатов, является ли набор Python более медленным, чем список Python?
Ответы:
Это зависит от того, что вы собираетесь с этим делать.
Наборы значительно быстрее, когда дело доходит до определения наличия объекта в наборе (как в x in s
), но медленнее, чем списки, когда дело доходит до перебора их содержимого.
Вы можете использовать модуль timeit, чтобы увидеть, что быстрее для вашей ситуации.
Списки немного быстрее, чем наборы, когда вы просто хотите перебрать значения.
Наборы, однако, значительно быстрее, чем списки, если вы хотите проверить, содержится ли в них элемент. Они могут содержать только уникальные предметы.
Оказывается, кортежи работают почти так же, как списки, за исключением их неизменности.
Итерация
>>> 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
Список производительности:
>>> import timeit
>>> timeit.timeit(stmt='10**6 in a', setup='a = range(10**6)', number=100000)
0.008128150348026608
Установить производительность:
>>> timeit.timeit(stmt='10**6 in a', setup='a = set(range(10**6))', number=100000)
0.005674857488571661
Возможно, вы захотите рассмотреть кортежи, так как они похожи на списки, но не могут быть изменены. Они занимают немного меньше памяти и имеют более быстрый доступ. Они не так гибки, но более эффективны, чем списки. Их обычное использование - служить словарными ключами.
Наборы также являются структурами последовательностей, но с двумя отличиями от списков и кортежей. Хотя наборы имеют порядок, этот порядок является произвольным и не контролируется программистом. Второе отличие состоит в том, что элементы в наборе должны быть уникальными.
set
по определению. [ питон | вики ].
>>> x = set([1, 1, 2, 2, 3, 3])
>>> x
{1, 2, 3}
set
ссылку встроенного типа ( docs.python.org/2/library/stdtypes.html#set ), а не устаревшую sets
библиотеку. Во-вторых, «Наборы также являются структурами последовательностей», считайте следующее из ссылки встроенного типа: «Будучи неупорядоченной коллекцией, наборы не записывают положение элемента или порядок вставки. Соответственно, наборы не поддерживают индексацию, нарезку или другие последовательное поведение. "
range
не list
. range
это специальный класс с пользовательским __contains__
магическим методом.
xrange
)
Set
выигрывает из-за почти мгновенных проверок "содержит": https://en.wikipedia.org/wiki/Hash_table
Реализация списка : обычно массив, низкий уровень, близкий к металлу, хороший для итерации и произвольного доступа по индексу элемента.
Реализация набора : https://en.wikipedia.org/wiki/Hash_table , он не выполняет итерацию по списку, но находит элемент, вычисляя хеш-код из ключа, поэтому он зависит от природы ключевых элементов и хеш-функции. функция. Подобно тому, что используется для dict. Я подозреваю, что list
может быть быстрее, если у вас очень мало элементов (<5), чем больше число элементов, тем лучшеset
будет проверка содержимого. Это также быстро для добавления и удаления элементов. Также всегда помните, что создание набора имеет свою стоимость!
ПРИМЕЧАНИЕ . Если объект list
уже отсортирован, поиск list
может быть довольно быстрым, но в обычных случаях set
он быстрее и проще для проверок содержимого.
Структуры данных (DS) важны, потому что они используются для выполнения операций с данными, что в основном подразумевает: принять некоторый ввод , обработать его и вернуть вывод .
Некоторые структуры данных более полезны, чем другие в некоторых конкретных случаях. Поэтому довольно несправедливо спрашивать, какой (DS) является более эффективным / быстрым. Это все равно, что спросить, какой инструмент более эффективен между ножом и вилкой. Я имею в виду, все зависит от ситуации.
Список является изменяемой последовательностью , обычно используемой для хранения коллекций однородных элементов. .
Заданный объект - это неупорядоченная коллекция различных хешируемых объектов. . Он обычно используется для проверки членства, удаления дубликатов из последовательности и вычисления математических операций, таких как пересечение, объединение, разность и симметричная разность.
Из некоторых ответов ясно, что список выполняется быстрее, чем набор при переборе значений. С другой стороны, набор быстрее списка, когда проверяется, содержится ли в нем элемент. Следовательно, единственное, что вы можете сказать, это то, что список лучше, чем набор для некоторых конкретных операций, и наоборот.
Меня интересовали результаты при проверке с помощью CPython, является ли значение одним из небольшого числа литералов. set
выигрывает в Python 3 против tuple
, list
и or
:
from timeit import timeit
def in_test1():
for i in range(1000):
if i in (314, 628):
pass
def in_test2():
for i in range(1000):
if i in [314, 628]:
pass
def in_test3():
for i in range(1000):
if i in {314, 628}:
pass
def in_test4():
for i in range(1000):
if i == 314 or i == 628:
pass
print("tuple")
print(timeit("in_test1()", setup="from __main__ import in_test1", number=100000))
print("list")
print(timeit("in_test2()", setup="from __main__ import in_test2", number=100000))
print("set")
print(timeit("in_test3()", setup="from __main__ import in_test3", number=100000))
print("or")
print(timeit("in_test4()", setup="from __main__ import in_test4", number=100000))
Вывод:
tuple
4.735646052286029
list
4.7308746771886945
set
3.5755991376936436
or
4.687681658193469
От 3 до 5 литералов set
все еще выигрывает с большим отрывом и or
становится самым медленным.
В Python 2 set
всегда самый медленный. or
является самым быстрым для 2 до 3 литер, а tuple
и list
быстрее с 4 или более литералов. Я не мог отличить скорость tuple
против list
.
Когда тестируемые значения кэшировались в глобальной переменной вне функции, вместо создания литерала в цикле, set
каждый раз выигрывал, даже в Python 2.
Эти результаты применимы к 64-битному CPython на Core i7.
Я бы порекомендовал реализацию Set, где вариант использования ограничен ссылками или поиском существования, и реализацию Tuple, где вариант использования требует от вас выполнения итерации. Список является низкоуровневой реализацией и требует значительных накладных расходов памяти.
from datetime import datetime
listA = range(10000000)
setA = set(listA)
tupA = tuple(listA)
#Source Code
def calc(data, type):
start = datetime.now()
if data in type:
print ""
end = datetime.now()
print end-start
calc(9999, listA)
calc(9999, tupA)
calc(9999, setA)
Вывод после сравнения 10 итераций для всех 3: Сравнение
Наборы работают быстрее, но вы получаете больше функций с наборами, например, допустим, у вас есть два набора:
set1 = {"Harry Potter", "James Bond", "Iron Man"}
set2 = {"Captain America", "Black Widow", "Hulk", "Harry Potter", "James Bond"}
Мы можем легко объединить два набора:
set3 = set1.union(set2)
Узнайте, что общего в обоих:
set3 = set1.intersection(set2)
Узнайте, что отличается в обоих:
set3 = set1.difference(set2)
И многое другое! Просто попробуйте, они веселые! Более того, если вам приходится работать с различными значениями в двух списках или общими значениями в двух списках, я предпочитаю преобразовывать ваши списки в наборы, и многие программисты делают это таким образом. Надеюсь, это поможет вам :-)