У 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
Ви можете розглянути Tuples подібні до списків, але їх неможливо змінити. Вони займають трохи менше пам’яті і швидше отримують доступ. Вони не такі гнучкі, але ефективніші, ніж списки. Їх звичайне використання - це функція клавіш словника.
Набори - це також структури послідовностей, але з двома відмінностями від списків і кортежів. Хоча набори мають порядок, цей порядок є довільним і не під контролем програміста. Друга відмінність полягає в тому, що елементи в наборі повинні бути унікальними.
set
за визначенням. [ пітон | wiki ].
>>> 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 , вона не повторює список, але знаходить елемент, обчислюючи хеш з ключа, тому це залежить від характеру ключових елементів та хеша функція. Аналогічно тому, що використовується для диктату. Я підозрюю, що list
може бути швидше, якщо у вас буде дуже мало елементів (<5), чим більший елемент рахується, тим краще set
буде виконати перевірку на вміст. Це також швидко для додавання та видалення елементів. Також завжди пам’ятайте, що побудова комплекту має вартість!
ПРИМІТКА : Якщо list
вже відсортовано, пошук list
може бути досить швидким, але для звичайних випадків a 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)
І набагато більше! Просто спробуйте їх, вони веселі! Крім того, якщо вам доведеться працювати над різними значеннями в 2 списку або загальними значеннями в межах 2 списків, я вважаю за краще перетворити ваші списки в набори, і багато програмістів роблять це таким чином. Сподіваюся, це допоможе вам :-)