Seite 1 von 1

Bessere Implementierung möglich?

Verfasst: Dienstag 17. Juli 2007, 16:25
von apollo13
Wenn ja bitte mit ganz kurzer Erklärung :)

Der Code:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def slice_it(my_list, columns=2):
    """slice_it(my_list, columns=2): Gibt eine Liste, die `columns` Listen
    enthält zurück. Jede dieser Listen repräsentiert eine Spalte, wie sie
    in Zeitungen/Wörterbüchern zu finden sind.
    >>> slice_it(range(10))
    [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]
    >>> slice_it(range(10),3)
    [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]
    >>> slice_it(range(10),4)
    [[0, 1, 2], [3, 4, 5], [6, 7], [8, 9]]
    """
    length = len(my_list)
    mod = length % columns
    step = length/columns
    pos = 0
    new_list = []
    i = 0
    while i < columns:
        if mod != 0:
            new_pos = pos+step+1
            new_list.append(my_list[pos:new_pos])
            pos = new_pos
            mod -= 1
        else:
            new_pos = pos+step
            new_list.append(my_list[pos:new_pos])
            pos = new_pos
        i += 1
    return new_list

if __name__ == "__main__":
    import doctest
    doctest.testmod()
    print "Tests done."
Thx, apollo13[/code]

Verfasst: Dienstag 17. Juli 2007, 17:42
von EyDu
Was meinst du mit besser? Ich habe es lediglich etwas kürzer:

Ganz kurz und grausam:

Code: Alles auswählen

def slice_it(li, cols=2):
	lengths = [len(li[i::cols]) for i in range(cols)]
	return [li[sum(lengths[:i]):sum(lengths[:i])+lengths[i]] for i in range(cols)]
Besser lesbar durch eine for-Schleife:

Code: Alles auswählen

def slice_it(li, cols=2):
	lengths = [len(li[i::cols]) for i in range(cols)]
	result = []
	for i in range(cols):
		start = sum(lengths[:i])
		stop = start + lengths[i]
		result.append(li[start:stop])
	return result
Und natürlich noch als Generator-Funktion:

Code: Alles auswählen

def slice_it(li, cols=2):
	lengths = [len(li[i::cols]) for i in range(cols)]
	for i in range(cols):
		start = sum(lengths[:i])
		stop = start + lengths[i]
		yield li[start:stop]
Edit: Da ist mir noch was schöneres eingefallen:

Code: Alles auswählen

def slice_it(li, cols=2): 
    start = 0
    for i in range(cols): 
        stop = start + len(li[i::cols])
        yield li[start:stop]
        start = stop

Verfasst: Dienstag 17. Juli 2007, 18:02
von apollo13
Wow, thx :)

Verfasst: Dienstag 17. Juli 2007, 18:29
von lunar
Du solltest xrange verwenden, solange du nicht wirklich eine Liste mit Zahlenwerten benötigst.

Verfasst: Dienstag 17. Juli 2007, 18:36
von Y0Gi
Erinnert mich an http://genshi.edgewall.org/wiki/HelperFunctions

Kürzeste Variante da:

Code: Alles auswählen

def group(iterable, num):
    """Group an iterable into an n-tuples iterable. Incomplete tuples
    are discarded e.g.
    
    >>> list(group(range(10), 3))
    [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, None, None)]
    """
    return map(None, *[iter(iterable)] * num)

Verfasst: Dienstag 17. Juli 2007, 18:42
von birkenfeld
Ouh, das ist aber ziemlich gewagt...

Verfasst: Dienstag 17. Juli 2007, 19:29
von EyDu
lunar hat geschrieben:Du solltest xrange verwenden, solange du nicht wirklich eine Liste mit Zahlenwerten benötigst.
Meine Code ist halt schon Python-3000-kompatibel :D

Verfasst: Dienstag 17. Juli 2007, 22:20
von apollo13
lunar hat geschrieben:Du solltest xrange verwenden, solange du nicht wirklich eine Liste mit Zahlenwerten benötigst.
Du meinst wegen dem Geschwindigkeitsvorteil?
Y0Gi hat geschrieben:Erinnert mich an http://genshi.edgewall.org/wiki/HelperFunctions
Kürzeste Variante da: ...
Hmm ich weiß aber die Nummer nicht, ich will die Columns angeben. Trotzdem interessantes Beispiel, danke. Ich glaub ich muss mir map mal genau anschauen...
birkenfeld hat geschrieben:Ouh, das ist aber ziemlich gewagt...
Was ist gewagt und warum?
EyDu hat geschrieben:Meine Code ist halt schon Python-3000-kompatibel :D
Wieso, gibt es dann kein xrange mehr?

Thx, apollo13

Verfasst: Dienstag 17. Juli 2007, 22:49
von veers
apollo13 hat geschrieben:Wieso, gibt es dann kein xrange mehr?
Weil sich range dann wie xrange verhalten wird. ;)

Verfasst: Mittwoch 18. Juli 2007, 09:00
von lunar
apollo13 hat geschrieben:
lunar hat geschrieben:Du solltest xrange verwenden, solange du nicht wirklich eine Liste mit Zahlenwerten benötigst.
Du meinst wegen dem Geschwindigkeitsvorteil?
Und Speicherverbrauch!

Code: Alles auswählen

for i in range(1000000):
     print i
Dieser Code erzeugt erst eine Liste mit einer Million Elementen im Speicher, bevor die Iteration beginnt, und hält diese Liste noch dazu die ganze Zeit im Speicher, obwohl die vorherigen Elemente nicht gebraucht werden.

Und was Python-3000 angeht: Ich wünsche mir jetzt schon happy porting ;)