Функция стандартной библиотеки Python для реорганизации списка - PullRequest
7 голосов
/ 22 августа 2011

Мне интересно, есть ли в Python стандартная библиотечная функция, которая будет переставлять элементы списка, как показано ниже:

a = [1,2,3,4,5,6,7]

function(a)

print a

a = [1,7,2,6,3,5,4]

Он должен получить один элемент из начала исходного списка, затем один из конца, затем второй из начала и так далее. Затем измените список.

С уважением,

Ответы [ 5 ]

9 голосов
/ 22 августа 2011

Вы можете создать быстрый, эффективный по памяти генератор , используя itertools, который делает то, что вы хотите:

from itertools import chain, izip

def reorder(a):
    gen = chain.from_iterable(izip(a, reversed(a)))
    for _ in a:
        yield next(gen)

>>> list(reorder(a))
<<< [1, 7, 2, 6, 3, 5, 4]

Вы найдете, что itertools имеет большую коллекцию строительных блоков для создания собственных эффективных итераторов.Немного более лаконичное решение:

>>> list(chain.from_iterable(izip(a, reversed(a))))[:len(a)]
<<< [1, 7, 2, 6, 3, 5, 4]

Понимание списков - еще один очень лаконичный способ построения списков:

>>> [x for t in zip(a, reversed(a)) for x in t][:len(a)]
<<< [1, 7, 2, 6, 3, 5, 4]

Наконец, вот краткий однострочныйПриколы:

>>> sum(zip(a, a[::-1]), ())[:len(a)]
<<< (1, 7, 2, 6, 3, 5, 4)
3 голосов
/ 22 августа 2011
>>> ((a+a[:0:-1])*len(a))[::len(a)][:len(a)]
[1, 7, 2, 6, 3, 5, 4]
2 голосов
/ 22 августа 2011

Конечно, в Python есть только один способ сделать что-то; -):

def function(a):
    ret = []
    this_end, other_end = 0, -1
    while a:
        ret.append(a.pop(this_end))
        this_end, other_end = other_end, this_end
    return ret

a = [1,2,3,4,5,6,7]

print function(a)

Для времени:

% python -m timeit 'def function(a):
quote>     ret = []
quote>     this_end, other_end = 0, -1
quote>     while a:
quote>         ret.append(a.pop(this_end))
quote>         this_end, other_end = other_end, this_end
quote>     return ret
quote>
quote> a = [1,2,3,4,5,6,7]
quote>
quote> print function(a)
quote> ' | tail
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
100000 loops, best of 3: 10.5 usec per loop
2 голосов
/ 22 августа 2011
for a in ([1,2,3,4,5,6,7,8,9],
          [1,2,3,4,5,6,7,8],
          [1,2,3,4],
          [1,2,3],
          [1,2,],
          [1],
          []):
    print a
    [ a.insert(i,a.pop()) for i in xrange(1,len(a)+1,2)]
    print a,'\n'

результат

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 9, 2, 8, 3, 7, 4, 6, 5] 

[1, 2, 3, 4, 5, 6, 7, 8]
[1, 8, 2, 7, 3, 6, 4, 5] 

[1, 2, 3, 4]
[1, 4, 2, 3] 

[1, 2, 3]
[1, 3, 2] 

[1, 2]
[1, 2] 

[1]
[1] 

[]
[] 

Обновление 1

Сравнение с кодом Zeekay:

from time import clock


n = 100000


te = clock()
for i in xrange(n):
    a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
    [ a.insert(i,a.pop()) for i in xrange(1,len(a)+1,2)]
print clock()-te



from itertools import chain, izip
def reorder(a):
    gen = chain(*izip(a, reversed(a)))
    for _ in a:
        yield next(gen)

te = clock()
for i in xrange(n):
    a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
    a = list(reorder(a)) 
print clock()-te

результат

2.36667984339
5.00051766356

Мой методизменения a на месте

1 голос
/ 08 сентября 2011

спасибо всем, я написал свою собственную функцию:

def shake(list):
    """Gets a list and reorders the items,
       one from beginning, one from end"""
    #print "original list is: ", list
    new_list = []

    x = len(list) - 1
    y = len(list)/2

    for i in xrange(y):
        if list[i] not in new_list:
            new_list.append(list[i])
        if list[i+x] not in new_list:
            new_list.append(list[i+x])
        x -= 2

    if len(list)%2 == 1:
        new_list.append(list[y])

    #print "new list is: ", new_list 
    return new_list
...