2015-04-30 12 views
5

Mam problem, który polega na: otrzymaniu krotki z obiektami dowolnego typu i podzieleniu jej na dwie krotki: pierwszą, tylko z ciągami; drugi, tylko z liczbami.Jak podzielić krotkę na dwie w pytonowy sposób

W porządku. Algorytm standardem byłoby coś jak:

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

ten sposób możemy tylko iteracyjne raz.

Moje pytanie brzmi: czy istnieje sposób, aby zrobić to w bardziej pytony sposób? Jeden liniowiec?

Próbowałem

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

Ale to jest mniej wydajny, jak iteracyjne nad krotki wejściowej dwukrotnie.

Również

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

ma ten sam problem, jak my dwie iteracje. Czy byłoby to możliwe do powtórzenia tylko raz i nadal uzyskać wynik, lub ponieważ mam do czynienia z rozdzieleniem na dwie krotki, nie jest to możliwe?

Dzięki!

+3

Nie idź do "drogi pythonic", to pułapka, która nie służy niczemu i prawie zawsze redukuje raczej czytelny i łatwy do zrozumienia fragment kodu do bałaganu z 1-wierszowym kodem dekodera. Twoim celem powinien być kod sformatowany do formatu łatwego do utrzymania i czytania, a nie do jak najmniejszej liczby linii. –

+0

@TymoteuszPaul Jestem tego świadomy. W rzeczywistości nie używam tego kodu, ale czuję się ograniczony, gdy myślę o zrozumieniu listy i ostatnio to badam; ludzie z przepełnienia stosu zawsze robią na mnie wrażenie swoimi odpowiedziami, dlatego właśnie zastanawiam się, czy to możliwe! Ale dzięki za radę! Przecież "Jawny jest lepszy niż niejawny"! – RafaelC

+1

W języku Java z przyjemnością nazywamy to rozpraszaniem procesu! spliteratory ftw. – Shashank

Odpowiedz

3

Przypuszczam, że można zrobić coś takiego

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

To by uczynić go trochę bardziej pythonic chyba ... i wciąż dość czytelny.

Oczywiście można również umieścić go na liście zrozumieniem, ale nie świetny:

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

Lista rozumienie prostu dostaje się i rzucił jej w zasadzie jest nadużywany w pętli for.

+0

Bardzo, bardzo, bardzo miły sposób, w jaki tam dotarłeś! Naprawdę cieszę się z twojej odpowiedzi! Używanie zwrotu 'bool' jako indeksu było czymś, o czym nigdy bym nie pomyślał. Dziękuję bardzo! – RafaelC

+0

W jaki sposób poradzisz sobie z jego * "przedmiotami dowolnego typu" *? Twój kod dodaje listy, zestawy, itp. Do krotki liczb. –

+1

true jest to bardzo binarne rozwiązanie, w którym wszystkie elementy listy są posortowane na jeden z dwóch binów ... co jest zgodne z moim odczytaniem oryginalnego stwierdzenia problemu, więc powiem te proste typy na ciągi i nie-ciągi (które może lub nie może być wystarczająca) –

0

Spróbuj tego:

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

bardzo sprytny .... niestety nadal iteruje dwa razy :) ale to fajna odpowiedź, myślę (+1) –

+0

Naprawdę dobra alternatywa! Jednak, jak powiedział Joran, pętle są dwa razy lepsze niż moje kody! – RafaelC

+0

Chociaż kod jest doceniany, powinien zawsze mieć towarzyszące wyjaśnienie. To nie musi długo potrwać, ale jest spodziewane. – peterh

2

To nie jest jedno-liner, i to nawet nie jest odpowiednikiem tego, czego początkowo robi, ale można użyć pojemnik z listy, aby zapewnić funkcję „mapowania”:

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

Jak @PadraicCunningham zauważył w komentarzach, na Pythonie 2, można użyć basestring zamiast str uchwycić typów Unicode.

+0

To by się zepsuło, gdy tylko spotkasz się z żadnym intem lub str. –

+0

@PadraicCunningham Naprawiony, aby był niezniszczalny. – Shashank

+0

Tak, ale w końcu stracisz wszystkie pływaki, itd. –

Powiązane problemy