Bir python listesinin nth öğesini veya yoksa bir varsayılanı alma


144

Ben dictionary.get(key, default)listeleri için python eşdeğer arıyorum . Listenin n. Öğesini veya varsa varsayılan bir değeri almak için herhangi bir satır deyimi var mı?

Örneğin, myList almak istediğim bir liste myList[0], myListboş bir liste ise 5 .

Teşekkürler.

Yanıtlar:


124
l[index] if index < len(l) else default

Negatif endeksleri desteklemek için şunları kullanabiliriz:

l[index] if -len(l) <= index < len(l) else default

3
Ancak listenizde bir ad yoksa (örneğin, liste kavrayışında) çalışmaz.
Xiong Chiamiov

9
Negatif endeks örneğini unutmuş görünüyorsunuz. Örneğin. index == -1000000dönmelidir default.
nodakai

3
@nodakai, iyi bir nokta. Bazen bundan ısırıldım. negatif olabilseydi x[index] if 0 <= index < len(x) else defaultdaha iyi olurdu index.
Ben Hoyt

3
@nodakai wow - testin doğru şekilde kodlanmaya çalışılmaması için denemenin / denemenin kullanılmasının neden daha iyi olabileceğinin harika bir örneği. Hâlâ olacağını bildiğim bir dava için denemeye / dışarıya güvenmekten hoşlanmıyorum, ancak bu bunu dikkate alma isteğimi arttırıyor.
ToolmakerSteve

6
@ToolmakerSteve: için formülünüz valid_index()yanlış. Negatif endeksleri olan Python yasal - olması gerektiği -len(l) <= index < len(l).
Tim Pietzcker

57
try:
   a = b[n]
except IndexError:
   a = default

Düzenleme: TypeError onayını kaldırdım - muhtemelen arayanın bunu yapmasına izin vermek daha iyidir.


3
Bunu severim. Bağımsız değişken olarak yinelenebilir olarak çağırabilmeniz için bir işlevin etrafına sarmanız yeterlidir. Daha kolay okunur.
Noufal Ibrahim

35
(a[n:]+[default])[0]

Gibi bu iyi muhtemelen abüyüdükçe

(a[n:n+1]+[default])[0]

Bu işe yarar çünkü eğer a[n:]boş bir listen => len(a)

İşte bunun nasıl çalıştığına bir örnek range(5)

>>> range(5)[3:4]
[3]
>>> range(5)[4:5]
[4]
>>> range(5)[5:6]
[]
>>> range(5)[6:7]
[]

Ve tam ifade

>>> (range(5)[3:4]+[999])[0]
3
>>> (range(5)[4:5]+[999])[0]
4
>>> (range(5)[5:6]+[999])[0]
999
>>> (range(5)[6:7]+[999])[0]
999

5
Bunu açıklamak için yorum yapmadan gerçek kodla yazar mısınız?
Peter Hansen

1
@Peter Hansen, sadece golf oynuyorsam;) Ancak Python'un tüm sürümlerinde çalışır . Kabul edilen cevap sadece 2.5+ üzerinde çalışır
John La Rooy

3
Bununla birlikte, bir öğe seçmek için 3 geçici liste oluşturmayı ve 2 endekse erişmeyi gerektirir.
Joachim Jablon

Bunu asla "gerçek" kodda yapmasam da, kolayca bir python REPL'de kullanabileceğim güzel ve öz bir tekli astar, bu yüzden benim oyumu elde edersiniz.
Cookyt

next(iter(lst[i:i+1]), default)- şifreli çirkin tek gömlekli yarışmaya başka bir giriş.
jfs

28

Şunu keşfettim:

next(iter(myList), 5)

iter(l)bir yineleyici döndürür myList, next()yineleyici birinci elemanını tüketir ve yükseltir StopIteration, burada ikinci argüman olduğu varsayılan bir değere sahip denilen eğer hariç hatayı5

Bu sadece örneğinizde olduğu gibi 1. öğeyi istediğinizde çalışır, ancak sorunuzun metninde değil, bu yüzden ...

Ek olarak, bellekte geçici listeler oluşturmasına gerek yoktur ve bir adı olmasa bile her türlü yinelenebilir şekilde çalışır (bkz. Xiong Chiamiov'un gruszczy'nin cevabı hakkındaki yorumu)


3
Diğer cevaplarla birleştiğinde: next(iter(myList[n:n+1]), 5) Şimdi nth öğesi için çalışıyor .
Alfe

Bu liste olmayanlarla çalışmaz. Bu noktada, şunu deneyin: Bir IndexError daha iyi bir IMHO fikri gibi okunur. Ayrıca, bellekte bir liste oluşturur.
Joachim Jablon

tryVaryant tek astar (OP tarafından istedi sormak) değildir. Yalnızca listeler için çalışır, çünkü myListOP tarafından belirtildiği gibi bir liste (kesin olarak, dizine eklenebilir bir şeydir). Burada tek bir (veya hiçbiri) öğenin bir listesini oluşturduğum için bellekte bir kopya oluşturmak burada pahalı değil. Tabii, biraz tepegöz, ama bir döngüde milyonlarca kez yapmadığınız sürece bahsetmeye değmez. Btw, sanırım bir IndexErroristisna oluşturmak ve yakalamak muhtemelen daha maliyetli.
Alfe

okunabilirlik önemlidir :) Bir IndexError artırmanın önemli bir maliyeti olduğu noktadaysanız, belki de her şeyi Python'da yapmalısınız.
Joachim Jablon

20
(L[n:n+1] or [somedefault])[0]

1
+1 çünkü bu bana ne [] or ...yaptığımı öğrenmemi sağladı . Ancak, kişisel olarak kabul edilen çözümü kolayca okuyacağım (yeni başlayanlar için). Verilen bir yorum ile 'def' içine sarmak, bunu büyük ölçüde sorun olmayacak.
ToolmakerSteve

Ya Küresel olarak Yanlış olarak değerlendirilen bir şey olursa L[n] == Falseya da L[n] == Noneya L[n] == []da daha fazla?
Joachim Jablon

@JachimJablon: Hala çalışıyor. Dilim bir liste döndürür ve [False]doğrudur.
Ignacio Vazquez-Abrams

Oh, gerçekten kontrol değil, liste kontrol edildi fark etmedi.
Joachim Jablon

Bunu neden bir demet halinde sardın? Bence myval = l[n:n+1] or [somedefault]iyi çalışır mı?
Rotareti

8

... pitonun bir eşdeğer arayan dict.get(key, default)listeleri için

Genel tekrarlanabilirler için bunu yapan bir itertools tarifleri vardır. Kolaylık sağlamak için şunları yapabilirsiniz:> pip install more_itertools için bu tarifleri uygulayan bu üçüncü taraf kütüphanesini içe aktarabilir ve içe aktarabilirsiniz:

kod

import more_itertools as mit


mit.nth([1, 2, 3], 0)
# 1    

mit.nth([], 0, 5)
# 5    

detay

nthTarifin uygulanması :

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(itertools.islice(iterable, n, None), default)

Gibi dict.get(), bu araç eksik endeksler için bir varsayılan döndürür. Genel tekrarlanabilirler için geçerlidir:

mit.nth((0, 1, 2), 1)                                      # tuple
# 1

mit.nth(range(3), 1)                                       # range generator (py3)
# 1

mit.nth(iter([0, 1, 2]), 1)                                # list iterator 
# 1  

2

Ucuz bir çözüm, numaralandırma ile gerçekten bir diksiyon yapmak ve .get()her zamanki gibi kullanmaktır .

 dict(enumerate(l)).get(7, my_default)

1

@ Joachim's ile yukarıdakileri birleştirerek kullanabilirsiniz

next(iter(my_list[index:]), default)

Örnekler:

next(iter(range(10)[8:]), 11)
8
>>> next(iter(range(10)[12:]), 11)
11

Ya da, belki daha açık, ama len

my_list[index] if my_list[index:] else default

1

Python 3.4 kullanarak benzer contextlib.suppress(exceptions)bir getitem()yöntem oluşturmak için getattr().

import contextlib

def getitem(iterable, index, default=None):
    """Return iterable[index] or default if IndexError is raised."""
    with contextlib.suppress(IndexError):
        return iterable[index]
    return default
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.