简体   繁体   English

更多'Pythonic'方式替换列表shuffle

[英]More 'Pythonic' Way to alternate list shuffle

Trying to 'shuffle' a list with even number of items. 尝试使用偶数项目“混洗”一个列表。 Splitting the list, L in half and alternating taking an element from each. 拆分列表, L成两半并交替从每个中取一个元素。

I've tried pop , but that approach was unable to get me to a one-liner. 我试过pop ,但这种方法无法让我进入单行。 ( while loop) and I know there is likely some more succinct way to move through it. while循环),我知道可能有一些更简洁的方式来完成它。

The shuffle from random isn't exactly what I need, either – because that randomizes the entire order instead of alternating between the split list. 来自random shuffle也不是我所需要的 - 因为它使整个订单随机化而不是在拆分列表之间交替。

If a one-liner isn't possible, is that because it's more readable in a while loop? 如果不能使用单行,那是因为它在while循环中更具可读性吗?

def shuffle(L):
    '''
    I apologize in advance for how wet the following code is... 
    Example:
    >>> shuffle([1, 2, 3, 4, 5, 6])
    [1, 4, 2, 5, 3, 6]
    '''
    return [L[:(len(L)//2)][0], L[(len(L)//2):][0], L[:(len(L)//2)][1], L[(len(L)//2):][1], L[:(len(L)//2)][2], L[(len(L)//2):][2]]

other attempt: 其他尝试:

def shuffle(L):
    x, L_first, L_next, L = len(L), L[:(len(L)//2)], L[(len(L)//2):], []
    while len(L) != x:
        L.extend([L_first.pop(0), L_next.pop(0)])
    return L

Use slice assignment with a step: 使用切片分配和步骤:

def shuffle(l):
    result = [None] * len(l)

    # Put the first half of l in the even indices of result
    result[::2] = l[:len(l)//2]

    # Put the second half of l in the odd indices of result
    result[1::2] = l[len(l)//2:]

    return result

If I understand correctly, you could also opt for itertools.chain.from_iterable after zipping to get the alternating effect. 如果我理解正确,你也可以在压缩之后选择itertools.chain.from_iterable以获得交替效果。

from itertools import chain

def shuff(l):
    return list(chain.from_iterable(zip(l[:len(l)//2], l[len(l)//2:])))

Demo 演示

>>> shuff(list(range(1, 7))
[1, 4, 2, 5, 3, 6]

One possibility (requires an external library but the recipe can also be found in the itertools -recipes section ) is: 一种可能性(需要一个外部库,但配方也可以在itertools -recipes部分找到 )是:

from iteration_utilities import roundrobin

def shuffle(L):
    return list(roundrobin(L[:len(L)//2], L[len(L)//2:]))

This is probably slower than list assignment but it also works for arbitary amounts of iterables without problems and it doesn't require odd-sized-input handling: 这可能比列表赋值慢,但它也适用于任意数量的迭代,没有问题,并且它不需要奇数大小的输入处理:

>>> shuffle([1, 2, 3, 4, 5, 6, 7])
[1, 4, 2, 5, 3, 6, 7]
>>> shuffle([1, 2, 3, 4, 5, 6])
[1, 4, 2, 5, 3, 6]

I did some timings and @user2357112 definetly has the fastest solution but my solution is at least on the second place (note that this graph is in log-log, that means the difference in absolute terms may seem smaller than it really is!): 我做了一些时间 ,@ user2357112 definetly有最快的解决方案,但我的解决方案至少在第二位(注意这个图是在log-log中,这意味着绝对值的差异可能看起来比它实际上小!):

在此输入图像描述


Disclaimer: I'm the author of that iteration_utilities library. 免责声明:我是iteration_utilities库的作者。

list comprehension with index calculation using modulo and floor division 列表理解与指数计算使用模数和地板划分

[ L[(i + (i % 2)*len(L))//2] for i in range(len(L)) ] # for case of even len(L)

still one line for the general case 对于一般情况仍然是一行

[ L[i//2 + (i % 2)*len(L)//2] for i in range(2*(len(L)//2)) ] + [L[-1]]*(len(L) % 2)

the index calc (i + (i % 2)*len(L))//2 指数calc (i + (i % 2)*len(L))//2

can be parsed as adding 可以解析为添加

i//2 which gives 0, 0, 1, 1, 2, 2 ... i//2给出0, 0, 1, 1, 2, 2 ...

and

(i % 2)*len(L)//2 where (i % 2) alternates 0, 1 for even/odd i (i % 2)*len(L)//2其中(i % 2)对偶数/奇数i交替0,1

0, len(L)//2, 0, len(L)//2, 0, len(L)//2 ...

sum: 和:

0, len(L)//2, 1, 1 + len(L)//2, 2, 2 + len(L)//2 ...

Found two solutions. 找到两个解决方案 First one is very unpythonic (using python 2.7) 第一个非常unpythonic(使用python 2.7)

a = [1, 2, 3, 4, 5, 6] # intial array

Method One (using string magic): 方法一(使用字符串魔法):

[int(p) for p in ' '.join([str(x) + ' ' + str(y) for x, y in zip(a[:len(a) / 2], a[len(a) / 2:])]).split(' ')]

Method Two: 方法二:

[i for Tuple in zip(a[:len(a) / 2], a[len(a) / 2:]) for i in Tuple]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM