Что является наиболее «питоническим»? способ перебрать список кусками?

Любые изменения loction (либо window.location или document.location) вызовут запрос на этот новый URL-адрес, если вы не просто изменяете фрагмент URL-адреса. Если вы измените URL-адрес, вы измените URL-адрес.

Используйте методы перезаписи URL-адресов на стороне сервера, такие как mod_rewrite от Apache , если вам не нравятся используемые вами URL-адреса.

417
задан Community 23 May 2017 в 12:34
поделиться

13 ответов

Измененный от эти рецепты раздел itertools Python документы:

from itertools import zip_longest

def grouper(iterable, n, fillvalue=None):
    args = [iter(iterable)] * n
    return zip_longest(*args, fillvalue=fillvalue)

Пример
В псевдокоде для хранения примера кратким.

grouper('ABCDEFG', 3, 'x') --> 'ABC' 'DEF' 'Gxx'

Примечание: на использовании Python 2 izip_longest вместо zip_longest.

290
ответ дан Boris 23 May 2017 в 12:34
поделиться
  • 1
    Да можно использовать. Но если строка уже известна, Вы don' t должен использовать ng-src. плоскость src была бы достаточна. Используйте ng-src если you' переменные интерполяции ре в HTML. – kumar_harsh 1 May 2014 в 05:39

Если списки имеют одинаковый размер, вы можете объединить их в списки из 4-х кортежей с помощью zip(). Например:

# Four lists of four elements each.

l1 = range(0, 4)
l2 = range(4, 8)
l3 = range(8, 12)
l4 = range(12, 16)

for i1, i2, i3, i4 in zip(l1, l2, l3, l4):
    ...

Вот что производит функция zip():

>>> print l1
[0, 1, 2, 3]
>>> print l2
[4, 5, 6, 7]
>>> print l3
[8, 9, 10, 11]
>>> print l4
[12, 13, 14, 15]
>>> print zip(l1, l2, l3, l4)
[(0, 4, 8, 12), (1, 5, 9, 13), (2, 6, 10, 14), (3, 7, 11, 15)]

Если списки большие, и вы не хотите объединять их в больший список, используйте itertools.izip(), который производит итератор, а не список.

from itertools import izip

for i1, i2, i3, i4 in izip(l1, l2, l3, l4):
    ...
0
ответ дан Brian Clapper 23 May 2017 в 12:34
поделиться

Мне нравится этот подход. Он простой и не магический, поддерживает все повторяемые типы и не требует импорта.

def chunk_iter(iterable, chunk_size):
it = iter(iterable)
while True:
    chunk = tuple(next(it) for _ in range(chunk_size))
    if not chunk:
        break
    yield chunk
1
ответ дан BallpointBen 23 May 2017 в 12:34
поделиться

Идеальное решение этой проблемы работает с итераторами (а не только с последовательностями). Это также должно быть быстро.

Это решение, предоставленное документацией для itertools:

def grouper(n, iterable, fillvalue=None):
    #"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

Используя ipython's %timeit на моем MacBook Air, я получаю 47,5 нас за цикл.

Тем не менее, это действительно не работает для меня, так как результаты дополняются до четных групп. Решение без дополнения немного сложнее. Наиболее наивное решение может быть:

def grouper(size, iterable):
    i = iter(iterable)
    while True:
        out = []
        try:
            for _ in range(size):
                out.append(i.next())
        except StopIteration:
            yield out
            break

        yield out

Простое, но довольно медленное: 693 нас за цикл

Лучшее решение, которое я мог бы найти, использует islice для внутреннего цикла:

def grouper(size, iterable):
    it = iter(iterable)
    while True:
        group = tuple(itertools.islice(it, None, size))
        if not group:
            break
        yield group

С тем же набором данных я получаю 305 нас за цикл.

Невозможно получить чистое решение быстрее, чем это, я предлагаю следующее решение с важным предостережением: если ваши входные данные содержат экземпляры filldata, вы можете получить неправильный ответ.

def grouper(n, iterable, fillvalue=None):
    #"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    for i in itertools.izip_longest(fillvalue=fillvalue, *args):
        if tuple(i)[-1] == fillvalue:
            yield tuple(v for v in i if v != fillvalue)
        else:
            yield i

Мне действительно не нравится этот ответ, но он значительно быстрее. 124 доллара США за цикл

7
ответ дан rhettg 23 May 2017 в 12:34
поделиться

Сначала я разработал его для разделения строк на подстроки для анализа строки, содержащей hex.
Сегодня я превратил его в сложный, но все же простой генератор.

def chunker(iterable, size, reductor, condition):
    it = iter(iterable)
    def chunk_generator():
        return (next(it) for _ in range(size))
    chunk = reductor(chunk_generator())
    while condition(chunk):
        yield chunk
        chunk = reductor(chunk_generator())

Аргументы:

Очевидные

  • iterable - это любые итерируемые / итераторы / генераторы, связывающие / генерирующие / перебирающие входные данные,
  • size - это, конечно, размер порции, которую вы хотите получить,

Более интересно

  • reductor - это вызываемый объект, который получает генератор, повторяющийся по содержание куска.
    Я ожидаю, что он вернет последовательность или строку, но я этого не требую.

    Вы можете передать в качестве этого аргумента, например, list, tuple, set, frozenset,
    или что-нибудь более причудливое. Я передал бы эту функцию, возвращая строку
    (при условии, что iterable содержит / генерирует / выполняет итерации по строкам):

    def concatenate(iterable):
        return ''.join(iterable)
    

    Обратите внимание, что reductor может вызвать закрытие генератор, возбуждая исключение.

  • condition является вызываемым объектом, который получает все, что вернуло reductor.
    Он решает утвердить & amp; вернуть его (вернув что-нибудь, оценивая True),
    или отклонить его & amp; завершить работу генератора (вернув что-нибудь другое или подняв исключение).

    Когда число элементов в iterable не делится на size, когда it исчерпан, reductor получит генератор, генерирующий меньше элементов, чем size.
    Давайте назовем эти элементы длится элементами .

    Я предложил две функции для передачи в качестве этого аргумента:

    • lambda x:x - будет получено последних элементов .

    • lambda x: len(x)==<size> - последние элементы будут отклонены.
      заменить <size>, используя число, равное size

0
ответ дан GingerPlusPlus 23 May 2017 в 12:34
поделиться
def chunker(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))
# (in python 2 use xrange() instead of range() to avoid allocating a list)

Простой. Легкий. Быстро. Работы с любой последовательностью:

text = "I am a very, very helpful text"

for group in chunker(text, 7):
   print repr(group),
# 'I am a ' 'very, v' 'ery hel' 'pful te' 'xt'

print '|'.join(chunker(text, 10))
# I am a ver|y, very he|lpful text

animals = ['cat', 'dog', 'rabbit', 'duck', 'bird', 'cow', 'gnu', 'fish']

for group in chunker(animals, 3):
    print group
# ['cat', 'dog', 'rabbit']
# ['duck', 'bird', 'cow']
# ['gnu', 'fish']
370
ответ дан nosklo 23 May 2017 в 12:34
поделиться
from itertools import izip_longest

def chunker(iterable, chunksize, filler):
    return izip_longest(*[iter(iterable)]*chunksize, fillvalue=filler)
11
ответ дан jfs 23 May 2017 в 12:34
поделиться
import itertools
def chunks(iterable,size):
    it = iter(iterable)
    chunk = tuple(itertools.islice(it,size))
    while chunk:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

# though this will throw ValueError if the length of ints
# isn't a multiple of four:
for x1,x2,x3,x4 in chunks(ints,4):
    foo += x1 + x2 + x3 + x4

for chunk in chunks(ints,4):
    foo += sum(chunk)

Иначе:

import itertools
def chunks2(iterable,size,filler=None):
    it = itertools.chain(iterable,itertools.repeat(filler,size-1))
    chunk = tuple(itertools.islice(it,size))
    while len(chunk) == size:
        yield chunk
        chunk = tuple(itertools.islice(it,size))

# x2, x3 and x4 could get the value 0 if the length is not
# a multiple of 4.
for x1,x2,x3,x4 in chunks2(ints,4,0):
    foo += x1 + x2 + x3 + x4
20
ответ дан Markus Jarderot 23 May 2017 в 12:34
поделиться

Я - поклонник

chunk_size= 4
for i in range(0, len(ints), chunk_size):
    chunk = ints[i:i+chunk_size]
    # process chunk of size <= chunk_size
117
ответ дан Boris 23 May 2017 в 12:34
поделиться

Так как никто не упомянул, что это все же вот zip() решение:

>>> def chunker(iterable, chunksize):
...     return zip(*[iter(iterable)]*chunksize)

Это работает, только если длина Вашей последовательности является всегда делимой размером блока, или Вы не заботитесь о запаздывающем блоке, если это не.

Пример:

>>> s = '1234567890'
>>> chunker(s, 3)
[('1', '2', '3'), ('4', '5', '6'), ('7', '8', '9')]
>>> chunker(s, 4)
[('1', '2', '3', '4'), ('5', '6', '7', '8')]
>>> chunker(s, 5)
[('1', '2', '3', '4', '5'), ('6', '7', '8', '9', '0')]

Или использование itertools.izip для возврата итератора вместо списка:

>>> from itertools import izip
>>> def chunker(iterable, chunksize):
...     return izip(*[iter(iterable)]*chunksize)

Дополнение может быть зафиксировано с помощью ответ @О¤О–О©О¤О–О™ОџОҐ's :

>>> from itertools import chain, izip, repeat
>>> def chunker(iterable, chunksize, fillvalue=None):
...     it   = chain(iterable, repeat(fillvalue, chunksize-1))
...     args = [it] * chunksize
...     return izip(*args)
6
ответ дан Community 23 May 2017 в 12:34
поделиться

Если список является большим, работающий самым высоким образом способ сделать, это должно будет использовать генератор:

def get_chunk(iterable, chunk_size):
    result = []
    for item in iterable:
        result.append(item)
        if len(result) == chunk_size:
            yield tuple(result)
            result = []
    if len(result) > 0:
        yield tuple(result)

for x in get_chunk([1,2,3,4,5,6,7,8,9,10], 3):
    print x

(1, 2, 3)
(4, 5, 6)
(7, 8, 9)
(10,)
3
ответ дан Robert Rossney 23 May 2017 в 12:34
поделиться

Кажется, нет симпатичного способа сделать это. Здесь страница, которая имеет много методов, включая:

def split_seq(seq, size):
    newseq = []
    splitsize = 1.0/size*len(seq)
    for i in range(size):
        newseq.append(seq[int(round(i*splitsize)):int(round((i+1)*splitsize))])
    return newseq
0
ответ дан Harley Holcombe 23 May 2017 в 22:34
поделиться

В Вашем втором методе я совершенствовался бы следующей группе 4 путем выполнения этого:

ints = ints[4:]

Однако я не сделал никакого измерения производительности, таким образом, я не знаю, какой мог бы быть более эффективным.

Однако я обычно выбирал бы первый метод. Это не симпатично, но это часто - последствие взаимодействия через интерфейс с внешним миром.

1
ответ дан Greg Hewgill 23 May 2017 в 22:34
поделиться