Python Setleri ve Listeler


187

Python'da hangi veri yapısı daha verimli / hızlı? Siparişin benim için önemli olmadığını ve yine de yinelenen kopyaları kontrol edeceğimizi varsayarsak, bir Python Python listesinden daha yavaş mı ayarlanmış?

Yanıtlar:


231

Onunla ne yapmak istediğinize bağlı.

Kümede bir nesnenin var olup olmadığını (olduğu gibi x in s) belirleme söz konusu olduğunda kümeler önemli ölçüde daha hızlıdır , ancak içerikleri üzerinde yineleme söz konusu olduğunda listelerden daha yavaştır.

Durumunuz için hangisinin daha hızlı olduğunu görmek için timeit modülünü kullanabilirsiniz .


4
Demek istediğin için: "Setler önemli ölçüde daha hızlı", onu daha hızlı yapan temel uygulama nedir?
50'de fazla döviz değişimi

Komut dosyası dilleri, temeldeki uygulamaları gizlemeyi sever, ancak bu görünür basitlik her zaman iyi bir şey değildir, bir yazılım tasarlarken bazı 'veri yapısı' farkındalığına ihtiyacınız vardır.
Christophe Roussy

4
Set, yineleme sırasında listeden önemli ölçüde yavaş değildir.
omerfarukdogan

39
Kümeler ve listelerin her ikisi de doğrusal zaman yinelemesine sahiptir. Birinin diğerinden "daha yavaş" olduğunu söylemek yanlış yönlendirilir ve bu yanıtı okuyan yeni programcıların kafasını karıştırır.
habnabit

ikisinin de doğrusal zaman yinelemesi olduğunu söylüyorsanız. Bu, aynı yineleme süresine sahip oldukları anlamına mı geliyor? O zaman fark nedir?
Mohammed Noureldin

153

Değerler üzerinde yineleme yapmak istediğinizde listeler setlerden biraz daha hızlıdır.

Bununla birlikte, içinde bir öğenin bulunup bulunmadığını kontrol etmek istiyorsanız setler listelerden çok daha hızlıdır. Yine de sadece benzersiz öğeler içerebilirler.

Görünüşe göre, tupller, değişmezlikleri hariç, listelerle neredeyse aynı şekilde performans gösteriyorlar.

yineleme

>>> 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

Bir nesnenin mevcut olup olmadığını belirleme

>>> 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

6
(Başlatma seti -> 5.5300979614257812) (Başlatma listesi -> 1.8846848011016846) (Başlatma grubu -> 1.8730108737945557) 12GB RAM ile intel core i5 dört çekirdekli 10.000 boyutundaki öğeler. Bu da dikkate alınmalıdır.
ThePracticalOne

4
Şimdi nesne oluşturma kaldırmak için kodu güncelledim. Timeit döngülerinin kurulum aşaması yalnızca bir kez çağrılır ( docs.python.org/2/library/timeit.html#timeit.Timer.timeit ).
Ellis Percival

7

Liste performansı:

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

Performansı ayarlayın:

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

Tuples'ı listelere benzediği, ancak değiştirilemediği için düşünebilirsiniz . Biraz daha az bellek kaplarlar ve erişimleri daha hızlıdır. Esnek değildirler, ancak listelerden daha verimlidirler. Normal kullanımları sözlük anahtarları olarak görev yapmaktır.

Kümeler aynı zamanda dizi yapılarıdır, ancak listelerden ve gruplardan iki farklılığa sahiptir. Setlerin bir sırası olmasına rağmen, bu sıra programcı kontrolü altında değil keyfi bir şekilde yapılır. İkinci fark, bir kümedeki öğelerin benzersiz olması gerektiğidir.

settanım olarak. [ python | wiki ].

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

4
Öncelikle , kullanımdan kaldırılmış kitaplığa değil, setyerleşik tür bağlantısına ( docs.python.org/2/library/stdtypes.html#set ) güncelleme yapmalısınızsets . İkincisi, "Kümeler de sıra yapılarıdır", yerleşik tür bağlantısından aşağıdakileri okuyun: "Sırasız bir koleksiyon olan kümeler, öğenin konumunu veya ekleme sırasını kaydetmez. Buna göre, kümeler dizin oluşturma, dilimleme veya diğerlerini desteklemez sekans benzeri davranış. "
Seaux

7
rangedeğil list. rangeözel __contains__büyü yöntemi ile özel bir sınıftır .
Ryne Wang

@RyneWang bu doğru, ama sadece Python3 için. Python2 aralığında normal bir liste döndürüyor (bu yüzden böyle korkunç şeyler var xrange)
Manoel Vilela

7

Setanında 'içerme' çekleri nedeniyle kazanır: https://en.wikipedia.org/wiki/Hash_table

Liste uygulaması: genellikle bir dizi, metale yakın düşük seviye, yineleme için iyi ve eleman indeksine göre rastgele erişim.

Uygulamayı ayarlayın : https://en.wikipedia.org/wiki/Hash_table , bir listede yinelenmez, ancak anahtardan bir karma hesaplayarak öğeyi bulur , bu nedenle anahtar öğelerin ve karma değerin doğasına bağlıdır. işlevi. Dikte için kullanılana benzer. listÇok az elemanınız (<5) varsa daha hızlı olabileceğinden şüpheleniyorum , daha büyük eleman sayısı, setbir kontrol için daha iyi performans gösterecektir. Ayrıca eleman ekleme ve çıkarma için hızlıdır. Ayrıca her zaman bir set oluşturmanın bir maliyeti olduğunu unutmayın!

NOT : listZaten sıralanmışsa, arama işlemi listoldukça hızlı olabilir, ancak olağan durumlarda a set, kontroller için daha hızlı ve daha basittir.


8
Metale yakın mı? Python bağlamında bu ne anlama geliyor? Bir liste metale bir setten nasıl daha yakındır?
roganjosh

@roganjosh, python hala bir makinede çalışıyor ve 'dizi' listesi gibi bazı uygulamalar donanımın iyi olduğu şeye daha yakın: stackoverflow.com/questions/176011/… , ancak her zaman ne elde etmek istediğinize bağlıdır, sadece soyutlamalar değil, uygulamalar hakkında biraz bilgi sahibi olmak iyidir.
Christophe Roussy

2

tl; Dr.

Veri yapıları (DS) önemlidir, çünkü bunlar temelde ima edilen veriler üzerinde işlemler yapmak için kullanılır: bir miktar girdi alın , işleyin ve çıktıyı geri verin .

Bazı veri yapıları bazı özel durumlarda diğerlerinden daha kullanışlıdır. Bu nedenle, hangi (DS) 'nin daha verimli / hızlı olduğunu sormak haksızlıktır. Bıçak ve çatal arasında hangi aracın daha verimli olduğunu sormak gibidir. Yani her şey duruma bağlı.

Listeler

Liste , tipik olarak homojen öğelerin koleksiyonlarını saklamak için kullanılan değiştirilebilir bir dizidir .

Setler

Bir küme nesnesi, ayrı yıkanabilir nesnelerin sırasız bir koleksiyonudur . Üyeliği test etmek, bir diziden yinelenenleri kaldırmak ve kavşak, birleşim, fark ve simetrik fark gibi matematiksel işlemleri hesaplamak için yaygın olarak kullanılır.

kullanım

Bazı cevaplardan, değerler üzerinde yineleme yaparken bir listenin kümeden daha hızlı olduğu açıktır. Öte yandan, içinde bir öğenin bulunup bulunmadığını kontrol ederken bir küme listeden daha hızlıdır. Bu nedenle, söyleyebileceğiniz tek şey, bir listenin bazı belirli işlemler için bir kümeden daha iyi olması ve bunun tersi.


2

CPython ile bir değerin az sayıdaki değişmezden biri olup olmadığını kontrol ederken sonuçlarla ilgileniyordum. setvs Python 3'te kazanır tuple, listve 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))

Çıktı:

tuple
4.735646052286029
list
4.7308746771886945
set
3.5755991376936436
or
4.687681658193469

3 ila 5 arasında, sethala geniş bir farkla orkazanır ve en yavaş olur.

Python 2'de sether zaman en yavaş olanıdır. or2 ila 3 değişmezleri için en hızlı ve tupleve listdaha hızlı 4 veya daha fazla değişmezleri ile. tupleVs hızını ayırt edemedim list.

Test edilecek değerler, döngü içinde değişmez değer oluşturmak yerine işlev dışında bir global değişken içinde önbelleğe alındığında, setPython 2'de bile her seferinde kazandı.

Bu sonuçlar Core i7'deki 64 bit CPython için geçerlidir.


0

Kullanım durumunun referans gösterme veya varoluş aramasıyla sınırlı olduğu bir Set uygulaması ve kullanım durumunun yinelemeyi gerçekleştirmenizi gerektirdiği Tuple uygulamasını öneririm. Liste, düşük düzeyli bir uygulamadır ve önemli miktarda bellek ek yükü gerektirir.


1
Gerçekten de, Setlerin ne zaman kullanılacağı ve Tuple'ın ne zaman kullanılacağı arasındaki uygun ayrım gerçekten çok önemlidir. Alt düzey bir API komut dosyası yazmadığım sürece ilgili bellek ek yükleri, ayak izleri konusunda endişe etmem.

0
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)

Tüm 3 için 10 yinelemeyi karşılaştırdıktan sonra çıktı: Karşılaştırma


0

Setler daha hızlıdır, morover, setlerle daha fazla fonksiyona sahip olursunuz, örneğin iki setiniz olduğunu varsayalım:

set1 = {"Harry Potter", "James Bond", "Iron Man"}
set2 = {"Captain America", "Black Widow", "Hulk", "Harry Potter", "James Bond"}

İki sete kolayca katılabiliriz:

set3 = set1.union(set2)

Her ikisinde de ortak olanı öğrenin:

set3 = set1.intersection(set2)

Her ikisinde de neyin farklı olduğunu öğrenin:

set3 = set1.difference(set2)

Ve daha fazlası! Sadece deneyin, eğlenceliler! Üstelik 2 listedeki farklı değerler veya 2 listedeki ortak değerler üzerinde çalışmak zorundaysanız, listelerinizi setlere dönüştürmeyi tercih ederim ve birçok programcı bu şekilde yapar. Umarım sana yardımcı olur :-)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.