Merge n从每个元素中交替列出k个元素

  • 本文关键字:元素 Merge python
  • 更新时间 :
  • 英文 :


我试图将任意数量的列表(包含在列表中(合并为一个列表,从每个列表中提取一定数量的k个元素。每个列表可以有不同的大小。

k = 2
mylist = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
[…]
print(modified_mylist)
> output: [1, 2, 5, 6, 8, 9, 12, 13, 3, 4, 7, 10, 11, 14, 15]

我在寻找一个"蟒蛇式"的解决方案。

编辑:以下是我试图实现的更详细的过程

[[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]

我将每个子列表拆分为k(在本例中为2(个元素的"块">

[ [ [1, 2], [3, 4] ], [ [5, 6], [7] ], [ [8, 9], [10, 11] ], [ [12, 13], [14, 15] ] ]

然后我交替地将每个块合并到一个单独的列表中

[ [1, 2], [5, 6], [8, 9], [12, 13], [3, 4], [7], [10, 11], [14, 15] ]

使列表变平,它变成

[1, 2, 5, 6, 8, 9, 12, 13, 3, 4, 7, 10, 11, 14, 15]
  1. more_itertools.chunked
  2. zip
  3. 然后变平:itertools.chainsum技巧
import itertools as it
import more_itertools as mit
data = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
def magic(data, k):
l = [list(mit.chunked(sub, k)) for sub in data]
l = list(zip(*l))
return(sum(it.chain(*l),[]))
magic(data,2)

输出:

[1, 2, 5, 6, 8, 9, 12, 13, 3, 4, 7, 10, 11, 14, 15]

注:

  • 我们可以避免使用生成器的中间列表:
    def magic(data, k):
    g = (mit.chunked(sub, k) for sub in data)
    g = zip(*g)
    return(sum(it.chain(*g),[]))
    
  • 或oneliner,以牺牲可读性为代价:
    magic = lambda d, k: sum(it.chain(*zip(*(mit.chunked(s,k) for s in d))), [])
    

这可以在单个列表理解中完成:

k = 2
L = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
out = [e for i in range(0,max(map(len,L)),k) for sl in L for e in sl[i:i+k]]
print(out)
[1, 2, 5, 6, 8, 9, 12, 13, 3, 4, 7, 10, 11, 14, 15]

这里有一个简单的解决方案,其中包含一些for循环。也许不是最蟒蛇的。

k = 3
mylist = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]
def magic(mylist, k):
# Empty list to store the chunked elements in
magic_list = []
# Loop over the list based on the length of the longest sublist and value of k
for i in range(0,max(map(lambda x: len(x), mylist)), k):
# Loop over the sublists
for l in mylist:
# Select the values in the span defined by K
magic_list += l[i:i+k]
return magic_list
magic(mylist, k)

输出:

[1, 2, 3, 5, 6, 7, 8, 9, 10, 12, 13, 14, 4, 11, 15]

我开始写一个长的响应,但这显然不是你想要的。

我们在这里可以做的是反转每个列表(为以后节省时间复杂性(,并继续弹出值,直到什么都没有了。

def magic(l, k):
result = []
# Reverse list
l = [list(reversed(a)) for a in l]
done = [False for v in l] # Keep track of which ones are done
while False in done:
# Iterate through,
# removing the first two (last because of the reverse) where possible
for i in range(len(l)):
# Add to results k times
for j in range(k):
if len(l[i]) > 0:
result.append(l[i].pop()) # Add result
# Check if that sub-array is empty
if len(l[i]) == 0:
done[i] = True
return result

虽然它可能不是一句俏皮话和花里胡哨的话,但它更容易理解,而且绝对适用于您的示例。编辑:它现在适用于任何k

最新更新