Python'daki bir listede bir şey olup olmadığını kontrol edin


314

Python'da tuples listesi var ve SADECE tuple listede değilse (listede varsa, o zaman if dalı almak istemiyorum) şube almak istiyorum bir koşullu var

if curr_x -1 > 0 and (curr_x-1 , curr_y) not in myList: 

    # Do Something

Bu benim için gerçekten işe yaramıyor. Neyi yanlış yaptım?


1
Not olduğunu 3 -1 > 0 and (4-1 , 5) not in []Truenedenle hata operatör öncelik biri değildir.
Dan D.

6
"Benim için gerçekten çalışmıyor" ile ne demek istiyorsun? Ne olmasını bekliyorsun? Aslında ne olur? Hangi liste içeriği sorunu tetikliyor?
Karl Knechtel

Neden denemiyorsunuz myList.count((curr_x, curr_y)), eğer değilse (curr_x, curr_y), myListsonuç olacak0
LittleLittleQ


2
Bu "kodum benim için gerçekten çalışmıyor" sorusunu 297 upvotes nasıl aldı? Lütfen bize minimal tekrarlanabilir bir örnek verin .
gerrit

Yanıtlar:


503

Hata muhtemelen kodunuzda başka bir yerde, çünkü iyi çalışıyor:

>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True

Veya tuples ile:

>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True

11
@Zack: Bunu bilmiyorsan, yapabilirsinif not ELEMENT in COLLECTION:
ninjagecko

@ninjagecko: daha az verimli ve hatta yanlış olabilecek kap türüne bağlı olarak. Bkz . Çiçeklenme filtreleri .
orlp

14
@nightcracker Yani hiçbir mantıklı A not in Byapıyor indirgenir not B.__contains__(A)hangi şifreyle aynıdır not A in Bolan düşürülür not B.__contains__(A).
Dan D.

1
Oh vay be, Python'un böyle bir şeye sahip olduğuna yemin edebilirdim __notcontains__. Üzgünüm, o zaman söylediklerim saçmalık.
orlp

2
@ std''OrgnlDave Olabilecek tek yol, notöncekinden daha yüksek önceliğe sahip olmaktır in. Sonucunu düşünün ast.dump(ast.parse("not A in B").body[0])sonuçlanır hangi "Expr(value=UnaryOp(op=Not(), operand=Compare(left=Name(id='A', ctx=Load()), ops=[In()], comparators=[Name(id='B', ctx=Load())])))"If notA sıkıca gruplandırılmış biri olması sonucunu umuyordum "Expr(value=Compare(left=UnaryOp(op=Not(), operand=Name(id='A', ctx=Load())), ops=[In()], comparators=[Name(id='B', ctx=Load())]))"için ayrıştırma olan "(not A) in B".
Dan D.

20

Python'daki bir listede bir şeyin olup olmadığını nasıl kontrol ederim?

En ucuz ve en okunabilir çözüm inoperatörü kullanmaktır (veya özel durumunuzda not in). Belgelerde belirtildiği gibi,

Operatörler inve not inüyelik testi. x in solarak değerlendirilirse True, eğer xbir üyesidir sve Falseaksi. x not in solumsuzluğunu döndürür x in s.

Bunlara ek olarak,

Operatör not in, ters gerçek değerine sahip olacak şekilde tanımlanır in.

y not in xmantıksal olarak aynıdır not y in x.

İşte birkaç örnek:

'a' in [1, 2, 3]
# False

'c' in ['a', 'b', 'c']
# True

'a' not in [1, 2, 3]
# True

'c' not in ['a', 'b', 'c']
# False

Bu aynı zamanda tuples ile de çalışır, çünkü tupler yıkanabilir (ayrıca değişmez olmalarının bir sonucu olarak):

(1, 2) in [(3, 4), (1, 2)]
#  True

RHS üzerindeki nesne bir __contains__()yöntem tanımlarsa , dokümanların Karşılaştırma bölümünün inson paragrafında belirtildiği gibi dahili olarak çağıracaktır .

... inve not inyinelenebilir veya __contains__()yöntemi uygulayan türler tarafından desteklenir . Örneğin, bunu yapabilirsiniz (ancak yapmamalısınız):

[3, 2, 1].__contains__(1)
# True

inkısa devreler, bu nedenle öğeniz listenin inbaşındaysa daha hızlı değerlendirir:

lst = list(range(10001))
%timeit 1 in lst
%timeit 10000 in lst  # Expected to take longer time.

68.9 ns ± 0.613 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
178 µs ± 5.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Bir öğenin listede olup olmadığını kontrol etmekten daha fazlasını yapmak istiyorsanız, seçenekler vardır:

  • list.indexbir öğenin dizinini almak için kullanılabilir. Bu öğe yoksa, a ValueErroryükseltilir.
  • list.count olayları saymak istiyorsanız kullanılabilir.

XY Sorunu: Bunu düşündünüz mü set?

Kendinize şu soruları sorun:

  • bir öğenin listede birden fazla olup olmadığını kontrol etmeniz gerekiyor mu?
  • Bu kontrol bir döngü içinde mi yoksa tekrar tekrar çağrılan bir fonksiyonda mı yapılıyor?
  • Listenizde sakladığınız öğeler yıkanabilir mi? IOW, hashonları arayabilir misin ?

Bu sorulara "evet" yanıtı verdiyseniz, setbunun yerine bir tane kullanmalısınız. S ile ilgili bir inüyelik testi listO (n) zaman karmaşıklığıdır. Bu, python'un listenizi doğrusal bir şekilde taraması, her bir öğeyi ziyaret etmesi ve arama öğesiyle karşılaştırması gerektiği anlamına gelir. Bunu tekrar tekrar yapıyorsanız veya listeler büyükse, bu işlem bir ek yüke neden olur.

setnesneler ise sürekli üyelik kontrolü için değerlerini toplar. Kontrol ayrıca aşağıdakiler kullanılarak yapılır in:

1 in {1, 2, 3} 
# True

'a' not in {'a', 'b', 'c'}
# False

(1, 2) in {('a', 'c'), (1, 2)}
# True

Aradığınız / aramadığınız öğenin listenizin sonunda olması konusunda talihsizseniz, python listeyi sonuna kadar taramış olacaktır. Bu, aşağıdaki zamanlamalardan açıkça görülmektedir:

l = list(range(100001))
s = set(l)

%timeit 100000 in l
%timeit 100000 in s

2.58 ms ± 58.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
101 ns ± 9.53 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

Bir hatırlatma olarak, sakladığınız ve aradığınız öğeler yıkanabilir olduğu sürece bu uygun bir seçenektir. IOW, ya değişmez tipler ya da uygulayan nesneler olmalıdırlar __hash__.


2
Kümeler her zaman bir seçenek değildir (örneğin, değiştirilebilir öğelerin bir listesine sahipken). Büyük koleksiyonlar için: seti bir arama için oluşturmak zaten O (n) süresidir ve bellek kullanımınızı iki katına çıkarabilir. Halihazırda bir aramaya sahip değilseniz, bir tane yapmak / sürdürmek her zaman en iyi seçim değildir.
wim
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.