Soru Python iterator'dan son öğeyi almanın en temiz yolu


Python 2.6'da son öğeyi bir yineleyiciden almanın en iyi yolu nedir? Örneğin, söyle

my_iter = iter(range(5))

En kısa kod / en temiz yol nedir? 4 itibaren my_iter?

Bunu yapabilirdim, ama çok verimli görünmüyor:

[x for x in my_iter][-1]

76
2018-01-26 10:53


Menşei


Yineleyiciler, öğeler arasında yinelemek istediğiniz ve son öğelere gerçekten erişmediğinizi varsayar. Sadece menzil kullanarak (5) [- 1] sizi ne engeller? - Frank
@Frank - Gerçek yineleyici daha karmaşık ve / veya daha uzak ve / veya kontrol etmek daha zor olduğunu düşündüm iter(range(5)) - Chris Lutz
@Frank: aslında yineleyiciyi sağlayan çok daha karmaşık bir jeneratör işlevi olduğu gerçeği. Sadece bu örneği hazırladım, böylece ne olduğunu basit ve açıktı. - Peter
Bir yineleyicinin son maddesini istiyorsanız, yanlış bir şey yaptığınız için büyük bir şans var. Ancak cevap, yineleyici boyunca yinelenen daha temiz bir yol olmadığını gösteriyor. Bunun nedeni, yineleyicilerin boyutlarının olmaması ve aslında hiç bitmeyecekleri ve bu nedenle son bir öğeye sahip olmayabilecekleridir. (Kodunuzun anlamı sonsuza dek sürecektir). Kalan soru şu: Neden bir yineleyicinin son maddesini istiyorsun? - Lennart Regebro
@Peter: Sorunuzu güncelleyin lütfen. Sahip olduğunuz bir soruya bir sürü yorum eklemeyin. Lütfen soruyu güncelleyin ve yorumları kaldırın. - S.Lott


Cevaplar:


item = defaultvalue
for item in my_iter:
    pass

70
2018-01-26 10:56



Yer tutucu neden "defaultvalue"? Neden olmasın None? Bu tam olarak ne None için. Bazı işleve özgü varsayılan değerlerin bile doğru olabileceğini mi düşünüyorsunuz? Yineleyici aslında yineleme yapmıyorsa, bant dışı bir değer Daha Bazı yanıltıcı fonksiyona özgü varsayılandan anlamlı. - S.Lott
Varsayılan değer, benim örneğim için sadece bir yer tutucudur. Kullanmak isterseniz None varsayılan değer olarak, bu sizin seçiminizdir. Hiçbiri her zaman en mantıklı varsayılan değildir ve hatta bant dışı bile olmayabilir. Şahsen ben gerçekten varsayılan bir benzersiz değer olduğundan emin olmak için 'defaultvalue = object ()' kullanma eğilimindedir. Sadece varsayılan seçimin bu örneğin kapsamı dışında olduğunu belirtiyorum. - Thomas Wouters
@ S.Lott: belki de boş bir yineleyici ile bir yineleyici arasındaki farkı ayırt etmek yararlıdır. None son değer olarak - John La Rooy
Tüm yerleşik muhafaza türlerinin tüm yineleyicileri için bir tasarım hatası var mı? İlk kez duydum :) - Thomas Wouters
Bu muhtemelen daha hızlı bir çözüm olsa da, döngüler için sızan değişkene dayanıyor (bazıları için bir özellik, diğerleri için bir hata - muhtemelen FP-adamlar dehşete düşüyor). Her neyse, Guido bunun her zaman böyle çalışacağını söyledi, bu yüzden kullanımı güvenli bir yapı. - tokland


Kullanın deque 1 numara.

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

41
2017-07-02 23:39



Bu aslında uzun bir diziyi tüketmenin en hızlı yoludur, ancak sadece döngüden daha hızlıdır. - Sven Marnach
Teknik olarak doğru olmak için +1, ancak okuyucular, "Bunu optimize etmek için gerçekten GEREKLİDİR?", "Bu, Pythonic olmayan daha az açık," ve "Daha hızlı hız, uygulamaya bağlıdır." değişebilir." - leewz
ayrıca, bir bellek-hog - Eelco Hoogendoorn
@EelcoHoogendoorn Neden bir max-1 ile bir bellek-hog nedir? - Chris Wesseling


Muhtemelen kullanmaya değer __reversed__ eğer mevcutsa

if hasattr(my_iter,'__reversed__'):
    last = next(reversed(my_iter))
else:
    for last in my_iter:
        pass

29
2018-02-05 23:01





Eğer python 3.x kullanıyorsanız:

*_, last = iterator # for a better understanding check PEP 448
print(last)

python 2,7 kullanıyorsanız:

last = next(iterator)
for last in iterator:
    continue
print last

22
2018-01-12 19:07



Lütfen açıklar mısınız *_ Bölüm? - virtualxtc
@virtualxtc check PEP 448 daha fazla ayrıntı için - DhiaTN
@virtualxtc: Alt çizgi sadece bir tanımlayıcıdır. Öndeki yıldız "listeyi genişlet" diyor. Daha okunaklı olurdu *lst, last = some_iterable. - pepr
@virtualxtc nope _ python'da özel bir değişkendir ve son değeri depolamak için ya da değerin umurumda olmadığını söylemek için kullanılır. - DhiaTN


Bu lambda nedeniyle boş döngüden daha hızlı olması olası değildir, ama belki başka birine bir fikir verecektir

reduce(lambda x,y:y,my_iter)

Eğer iter boşsa, bir TypeError yükseltilir


18
2018-01-26 11:59





Kadar basit:

max(enumerate(the_iter))[1]

16
2018-06-06 11:24



Oh, bu zekice. En verimli veya okunabilir değil, akıllı. - timgeb
Sadece yüksek sesle düşünüyorum ... çünkü bu enumerate döner (index, value) sevmek: (0, val0), (1, val1), (2, val2)... ve sonra varsayılan olarak max Bir tuple listesi verildiğinde, iki ilk değer eşit olmadıkça, tuple'ın yalnızca ilk değerine karşılık gelir; Ardından, izleyen alt simge, maksimum (idx, value) tuple değerini döndürür, oysa yalnızca ilgileniriz value. İlginç fikir. - Taylor Edmiston


İşte var

list( the_iter )[-1]

Yinelemenin uzunluğu gerçekten destansıysa - listeyi gerçekleştirecek kadar uzun bir süre bellek tüketir - o zaman gerçekten tasarımı yeniden düşünmeniz gerekir.


4
2018-01-26 11:42



Bu en basit çözümdür. - laike9m
Bir tuple kullanmak için biraz daha iyi. - Christopher Smith
Son cümle ile kesinlikle katılmıyorum. Çok büyük veri kümeleriyle çalışmak (hepsi bir kerede yüklüyse bellek sınırlarını aşabilir) bir liste yerine bir yineleyici kullanmanın ana nedenidir. - Paul
@Paul: Bazı işlevler yalnızca bir yineleyici döndürür. Bu, bu durumda bunu yapmak için kısa ve oldukça okunabilir bir yoldur (epik olmayan listeler için). - serv-inc


Kullanmak istiyorum reversedBunun dışında, yalnızca rasgele gibi görünen sıralar yerine diziler alması dışında.

Yaptığınız her şekilde, tüm yineleyici boyunca koşmanız gerekir. Maksimum verimde, tekrarlayıcıya bir daha ihtiyacınız yoksa, tüm değerleri çöpe atabilirsiniz:

for last in my_iter:
    pass
# last is now the last item

Bunun bir alt optimal çözüm olduğunu düşünüyorum.


2
2018-01-26 10:57



reversed () bir yineleyici, sadece dizileri almaz. - Thomas Wouters
Hiç keyfi değil. Bir yineleyiciyi geri almanın tek yolu, tüm öğeleri bellekte saklarken sonuna kadar tekrarlamaktır. Tersine çevirebilmen için önce bir sıra yapmalısın. Tabii ki, iteratörün amacını ilk olarak bozguna uğratır ve aynı zamanda aniden hiçbir sebepten ötürü çok fazla bellek kullanmanız anlamına gelir. Yani, aslında keyfi olanın tam tersidir. :) - Lennart Regebro
@Lennart - Keyfi dediğimde, can sıkıcı olmak demek istedim. Sabah saatlerinde birkaç saat içinde dil becerilerimi makaleme odaklıyorum. - Chris Lutz
Yeterince adil. Her ne kadar IMO, yineleyicileri kabul etseydi daha sinir bozucu olurdu, çünkü hemen hemen her kullanımı kötü bir fikir olurdu (tm). :) - Lennart Regebro


Benzer bir şey için bu kodu bakın:

http://excamera.com/sphinx/article-islast.html

ile son öğeyi almak için kullanabilirsiniz:

[(last, e) for (last, e) in islast(the_iter) if last]

1
2018-01-12 18:08



Lütfen kodu ekleyin islast cevabınızda meta.stackexchange.com/questions/8231/...). - Cristian Ciupitu


Sadece kullanırdım next(reversed(myiter))


0
2017-10-24 18:48



TypeError: reversed () argümanı bir dizi olmalı - Labo


Soru yanlıştır ve sadece karmaşık ve verimsiz bir cevaba yol açabilir. Bir yineleyici almak için, elbette yinelenebilir olan bir şeyden yola çıkabilirsiniz, ki bu çoğu durumda son öğeye erişmenin daha doğrudan bir yolunu sunacaktır.

Bir yineleyiciden bir yineleyici oluşturduktan sonra, elemanların içinden geçiyorsunuz, çünkü bu yinelenebilirliğin sağladığı tek şey.

Dolayısıyla, en verimli ve açık yol, yineleyiciyi ilk etapta yaratmak değil, yinelenebilirliğin doğal erişim yöntemlerini kullanmaktır.


-7
2018-06-29 02:37



Peki bir dosyanın son satırını nasıl alırsın? - Brice M. Dempsey