Seite 1 von 1

Liste mit tuple zu Liste mit ranges

Verfasst: Montag 11. August 2008, 14:38
von ete
Hallo!

Ich möchte folgende Liste:

liste = [[(10, 13), (15, 22)], [(19, 24)], [(20, 25)]]

in solche umwandeln:

[[10, 11, 12, 15, 16, 17, 18, 19, 20, 21], [19, 20, 21, 22, 23], [20, 21, 22, 23, 24]]
Also quasie die tuples in ranges umwandeln.
Mein Versuch funktioniert nur bedingt:

Code: Alles auswählen

liste2 = []
liste3 = []
for b in liste:
    if len(b) > 1:
        for a in b:
            start = a[0]
            end = a[1]
            bereich = range(start, end)
            liste2.extend(bereich)         
    else:
        start = b[0][0]
        end = b[0][1]
        bereich = range(start, end)  
        liste3.append(bereich)
liste3.append(liste2)
liste3.sort()
print liste3
Die Liste funktioniert z.B. nicht:
[[(10, 13), (15, 22)], [(13, 14), (19, 24)], [(20, 25)]]

Weiss jemand Rat?
Stefanie

Verfasst: Montag 11. August 2008, 15:06
von numerix
So ?

Code: Alles auswählen

multiliste_alt = [[(10, 13), (15, 22)], [(13, 14), (19, 24)], [(20, 25)]]
multiliste_neu = []
for liste in multiliste_alt:
    liste_neu = []
    for tupel in liste:
        liste_neu.extend(range(tupel[0],tupel[1]))
    multiliste_neu.append(liste_neu)
print multiliste_neu

Verfasst: Montag 11. August 2008, 15:12
von Trundle
Oder als List Comprehension (x ist hierbei die Eingangs-Liste):

Code: Alles auswählen

[sum((range(start, stop) for (start, stop) in intervals), list())
 for intervals in x]

Verfasst: Montag 11. August 2008, 15:42
von numerix
@Trundle: Beeindruckend! :shock:

Verfasst: Montag 11. August 2008, 16:49
von Trundle
Alternativ, da sum.__doc__ eigentlich nur von Zahlen spricht:

Code: Alles auswählen

from operator import add

[reduce(add, (range(start, stop) for (start, stop) in intervals))
 for intervals in x]

Verfasst: Montag 11. August 2008, 16:55
von numerix
Trundle hat geschrieben:Alternativ, da sum.__doc__ eigentlich nur von Zahlen spricht: ...
Ach, schade, gerade das mit sum() fand ich so genial. Auf die Idee, sum() für die Verkettung von Listen einzusetzen, wäre ich nämlich nie gekommen.

Verfasst: Montag 11. August 2008, 18:49
von audax

Code: Alles auswählen

from operator import add

def sum_(iterable, start=0):
    return reduce(add, iterable, start)

print sum_([1, 2, 3, 4])
print sum_([(1, 2), (2, 3)], tuple())


mehr macht des nicht, es ist also legitim das zum list flattening zu nutzen meiner Meinung nach :]

Verfasst: Montag 11. August 2008, 19:02
von audax
Meine Lösung nochmal:

Code: Alles auswählen

from itertools import starmap, imap

def flatten(iterable):
    return sum(iterable, [])

def to_ranges(ranges):
    return flatten(starmap(range, imap(tuple, ranges)))

liste = [[(10, 13), (15, 22)], [(19, 24)], [(20, 25)]] 

assert map(to_ranges, liste) == [[10, 11, 12, 15, 16, 17, 18, 19, 20, 21], [19, 20, 21, 22, 23], [20, 21, 22, 23, 24]] 

Verfasst: Montag 11. August 2008, 19:03
von BlackJack
Ein bisschen mehr mach `sum()` (leider) doch:

Code: Alles auswählen

In [2]: sum(['hallo', ' ', 'welt'], '')
---------------------------------------------------------------------------
<type 'exceptions.TypeError'>             Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

<type 'exceptions.TypeError'>: sum() can't sum strings [use ''.join(seq) instead]
Das es diesen "Spezialfall" mit einer Ausnahme quittiert, finde ich sehr unglücklich. Die Argumentation für dieses Verhalten, nämlich dass das bei Zeichenketten quadratische Laufzeit hat, gilt für Listen nämlich auch.

Verfasst: Montag 11. August 2008, 19:37
von audax
Darüber hab ich tatsächlich noch nicht nachgedacht und werde jetzt jedenfalls ne andere implementation von flatten() nehmen :]

Verfasst: Dienstag 12. August 2008, 09:11
von ete
Vielen Dank :shock:
List Compr. sind schon sehr beeindruckend...

Stefanie