【问题标题】:Python standard library function for rearranging a list用于重新排列列表的 Python 标准库函数
【发布时间】:2011-10-31 18:40:51
【问题描述】:

我想知道 Python 中是否有一个标准库函数可以重新排列列表的元素,如下所示:

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

function(a)

print a

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

它应该从原始列表的开头获取一个元素,然后从末尾获取一个元素,然后从开头获取第二个元素,依此类推。然后重新排列列表。

问候,

【问题讨论】:

  • 为什么会有人将它创建为标准库函数?您是否正在寻找用于生成 sestinas 的特定领域语言?
  • 这是重新排序列表的一种非常具体的方式。我非常怀疑是否有一个标准库函数可以做到这一点。幸运的是,你可以只写一个。
  • 我很确定没有 standard 功能可以满足您的要求。您可以使用列表组合。这将是非常小的
  • Python 是一种编程语言,而不是每个可以想象的程序的大量预构建集合。
  • @alwbtc: eknath 的意思是 list comprehensions

标签: python list function standards


【解决方案1】:
>>> ((a+a[:0:-1])*len(a))[::len(a)][:len(a)]
[1, 7, 2, 6, 3, 5, 4]

【讨论】:

  • 令人惊讶。但是(a+a[:0:-1])*len(a) 如果 len(a)==7 则长度为 91 个元素,如果 len(a)==100 则长度为 19900
  • @eyquem,当然效率不高,但是这个q确实引爆了我的作业雷达
【解决方案2】:

您可以使用itertools 构建一个快速、内存高效的generator,它可以满足您的需求:

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]

List comprehensions 是另一种非常简洁的构建列表的方法:

>>> [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)

【讨论】:

  • 不错!不过,为什么不gen = chain(*izip(a, reversed(a)))
  • 是的,实际上这样更好,因为reversed 返回一个迭代器。
  • 是的,但在那之后我崩溃了:(
  • 发生在我们最好的人身上。 :-)
  • *izip 内存效率不高,它必须同时扩展所有迭代器。你想要chain.from_iterable(izip(a, reversed(a)))
【解决方案3】:
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就地

【讨论】:

    【解决方案4】:

    当然,在 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
    

    【讨论】:

      【解决方案5】:

      谢谢大家,我自己写了函数:

      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
      

      【讨论】:

        猜你喜欢
        • 2015-01-01
        • 1970-01-01
        • 2017-07-25
        • 1970-01-01
        • 1970-01-01
        • 2015-09-16
        • 2014-12-18
        • 2023-02-24
        • 1970-01-01
        相关资源
        最近更新 更多