Witam Używam czegoś, co Funkcja Grouper z Ittools Pythona, aby wyciąć duże kawałki wyboru, gdzie w (idlist) zapytania do wydajności SQLite. Problemem jest Grouper wypełnia w całej przestrzeni chunksyzacji, nawet jeśli lista jest znacznie mniejsza, więc musiałem dodać pętlę i porównania, z którym teraz chcę zoptymalizować.

# input list shorter than grouper chunk size
input = (1,2,3,4,5)

grouper(10,input)
# desired output = (1,2,3,4,5)
# actual output = (1,2,3,4,5,None,None,None,None,None)

# current fix for this issue
list_chunks = tuple(tuple(n for n in t if n) for t in grouper(10, input))

Myślę, że musi istnieć sposób, aby to zrobić bez tej pętli i porównania.

Uwaga: Używanie Pythona 2.5

4
BillPull 30 sierpień 2012, 00:26

3 odpowiedzi

Najlepsza odpowiedź

Coś takiego?

>>> filter(bool, (1,2,3,4,5,None,None,None,None,None))
(1, 2, 3, 4, 5)

Dla bardziej skomplikowanego przypadku (np. Z 0 na liście lub musisz upuścić coś innego niż None) Możesz wdrożyć własny lambda:

>>> filter(lambda n: n is not None, (0,1,2,3,4,5,None,None,None,None,None))
(0, 1, 2, 3, 4, 5)

Lub nawet

>>> from functools import partial
>>> from operator import ne
>>> filter(partial(ne, None), (0,1,2,3,4,5,None,None,None,None,None))
(0, 1, 2, 3, 4, 5)
3
Alexey Kachayev 29 sierpień 2012, 20:35

Jeśli zamiast odfiltrować wpisy None, przepisać grouper(), aby zwrócić to, co chcesz, jest opcją, można użyć następującego rozwiązania przy użyciu itertools.islice:

def grouper(n, iterable):
    it = iter(iterable)
    x = tuple(islice(it, n))
    while x:
        yield x
        x = tuple(islice(it, n))

Lub krótszy odpowiednik (to nieco trudniejsze do zrozumienia):

def grouper(n, iterable):
    it = iter(iterable)
    return iter(lambda: tuple(islice(it, n)), ())

Przykład:

>>> list(grouper(5, range(12)))
[(0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10, 11)]
10
Andrew Clark 29 sierpień 2012, 20:42

Możesz użyć filter i map:

map(lambda x: filter(bool, x), grouper(10, my_input))

Oto przykład:

>>> my_input = (1,2,3,4,5,6,7,8,9,1,2,3,3)
>>> map(lambda x: filter(bool, x), list(grouper(10, my_input)))
[(1, 2, 3, 4, 5, 6, 7, 8, 9, 1), (2, 3, 3)]

Wreszcie można owinąć to w połączeniu tuple(), jeśli chcesz, aby była krotka zamiast listy.

1
Simeon Visser 29 sierpień 2012, 20:34