2015-04-30 31 views
5

Bir sorun var: herhangi bir türde nesnelerle bir tuple alma ve iki tuple ayırma: ilk, yalnızca dizelerle; ikincisi, sadece rakamlarla.Bir tuple, pythonic bir şekilde ikiye bölme

Tamam.

def separate(input_tuple): 
    return_tuple = ([],[]) 
    for value in input_tuple: 
     if isinstance(value, str): 
      return_tuple[0].append(value) 
     if isinstance(value, numbers.Number): 
      return_tuple[1].append(value) 
    return tuple([tuple(l) for l in return_tuple]) 

Bu şekilde, sadece kez yineleme: Standart algoritma gibi bir şey olurdu.

Sorum şu: daha pythonic bir şekilde yapmanın bir yolu var mı? Tek liner mı?

Ben

(tuple([i for i in input_tuple if isinstance(i,str)]), tuple([i for i in input_tuple if isinstance(i,numbers.Number)])) 

denedi Ama biz iki kez girdi başlığın üzerinde yineleme gibi, daha az verimlidir. iki yinelemeleri gibi Ayrıca

,

tuple([ tuple([i for i in input_tuple if isinstance(i, k)]) for k in ((float ,int,complex), str) ]) 

, aynı sorun vardır. Bu sadece bir kez yinelemek ve sonuç elde etmek mümkün olabilir mi, ya da iki tuple ayrılıyorum, mümkün değil mi?

Teşekkürler!

+3

"Pythonic yol" için gitme, iyi hizmet veren ve neredeyse her zaman okunabilir ve kolay anlaşılır bir kod parçasını 1-satır-kod çözücü-ring gerektiren bir karmaşaya indirgeyen bir tuzaktır. Amacınız, okunması ve okunması kolay olan, olabildiğince az satır içermeyen bir biçimde biçimlendirilmiş kodlara sahip olmak olmalıdır. –

+0

@TymoteuszPaul Bunun farkındayım. Aslında bu kodu kullanmıyorum ama liste anlama hakkında düşündüğümde kendimi kısıtlı hissediyorum ve son zamanlarda çalışıyorum; Yığın taşmasından insanlar beni her zaman cevaplarıyla etkiliyor, bu yüzden bu mümkün olup olmadığını merak ediyorum! Yine de tavsiye için teşekkürler! Sonuçta, 'Açık, örtük olmaktan iyidir'! – RafaelC

+1

Java'da, bu işlemi bölünmeye büyük bir özenle çağırıyoruz! spliterators ftw. – Shashank

cevap

3

Hala pythonic galiba ... ve oldukça okunabilir biraz daha yapacak Yani

my_tuple = ([],[]) 
for x in a_list: 
    my_tuple[isinstance(x,basestring)].append(x) 

gibi bir şey herhalde. Tabii

ayrıca bir liste anlama koymak ama büyük değil tek olabilir:

[my_tuple[isinstance(x,basestring)].append(x) for x in a_list] 

liste anlama sadece uzak attı alır ve onun temelde döngü için içine istismar ediliyor.

+0

Çok, çok, çok güzel bir yol var! Cevabınız beni çok memnun etti! İndeks olarak 'bool' iadesini kullanmak asla düşünemediğim bir şeydi. Çok teşekkür ederim! – RafaelC

+0

Yine de onun "herhangi bir türdeki nesneler" * ile nasıl başa çıkardınız? Kodunuz, tuple numaralarına listeler, kümeler vb. Ekler. –

+1

true, bu, listenin tüm öğelerinin, orijinal sorun bildirimini okumamı sağlayarak, bu basit sıraları dizelere ve dizeleri olmayanlara (yani olabilir ya da olmayabilir) –

0

deneyin bu bir:

tuple(list(filter(lambda e: isinstance(e, t), input_tuple)) for t in (str,int)) 
+0

çok zeki .... ne yazık ki hala iki kez yinelenen :) ama bu harika bir cevap olduğunu düşünüyorum (+1) –

+0

Gerçekten güzel bir alternatif! Ancak Joran'ın dediği gibi, kodlarımın iki katı geçiyor! – RafaelC

+0

Kod takdir edilmesine rağmen, her zaman eşlik eden bir açıklamaya sahip olmalıdır. Bu uzun olmak zorunda değil ama bekleniyor. – peterh

2

Bu tek liner değil ve bu, daha önce ne yaptıklarını bile denk değil, ancak bir "eşleştirme" fonksiyonunu sağlamak için listelerin bir kap kullanabilirsiniz:

>>> from numbers import Number 
>>> tup = (1, '2', 3, '4', 5) 
>>> di = {} 
>>> for x in tup: 
...  di.setdefault(Number if isinstance(x, Number) else str if isinstance(x, str) else object, []).append(x) 
... 
>>> di[str], di[Number] 
(['2', '4'], [1, 3, 5]) 

@PadraicCunningham açıklamalarda belirtildiği gibi, Python 2 için, sen basestring yerine str Unicode türlerini yakalamak için kullanabilirsiniz.

+0

Bu, herhangi bir int olmayan veya str –

+0

@PadraicCunningham sabit olmayan en kısa sürede kırılır kırılmaz yapmak için sabit. – Shashank

+0

Evet ama sonunda tüm floatlar eksik olacaksınız .. –