Python - 将数组拆分为多个数组

5

我有一个包含文件名的数组,如下所示:

['001_1.png', '001_2.png', '001_3.png', '002_1.png','002_2.png', '003_1.png', '003_2.png', '003_3.png', '003_4.png', ....]

我想要快速地将这些文件分组成多个数组,就像这样:
[['001_1.png', '001_2.png', '001_3.png'], ['002_1.png', '002_2.png'], ['003_1.png', '003_2.png', '003_3.png', '003_4.png'], ...]

有人能告诉我如何用几行Python代码实现吗?


2
在您期望的输出中,第三个元素应该是001_3.png吗? - tda
它总是这样的吗,我的意思是有序的吗? - BcK
第三张应该是001_3.png,对吗? - Vafliik
6个回答

6
如果您的数据已经按文件名排序,您可以使用itertools.groupby
files = ['001_1.png', '001_2.png', '001_3.png', '002_1.png','002_2.png',
        '003_1.png', '003_2.png', '003_3.png']

import itertools

keyfunc = lambda filename: filename[:3]

# this creates an iterator that yields `(group, filenames)` tuples,
# but `filenames` is another iterator
grouper = itertools.groupby(files, keyfunc)

# to get the result as a nested list, we iterate over the grouper to
# discard the groups and turn the `filenames` iterators into lists
result = [list(files) for _, files in grouper]

print(list(result))
# [['001_1.png', '001_2.png', '001_3.png'],
#  ['002_1.png', '002_2.png'],
#  ['003_1.png', '003_2.png', '003_3.png']]

否则,您可以基于这个配方编写代码,它比对列表进行排序然后使用groupby更有效率。
  • Input: Your input is a flat list, so use a regular ol' loop to iterate over it:

    for filename in files:
    
  • Group identifier: The files are grouped by the first 3 letters:

    group = filename[:3]
    
  • Output: The output should be a nested list rather than a dict, which can be done with

    result = list(groupdict.values())
    

组合起来:

files = ['001_1.png', '001_2.png', '001_3.png', '002_1.png','002_2.png',
        '003_1.png', '003_2.png', '003_3.png']

import collections

groupdict = collections.defaultdict(list)
for filename in files:
    group = filename[:3]
    groupdict[group].append(filename)

result = list(groupdict.values())

print(result)
# [['001_1.png', '001_2.png', '001_3.png'],
#  ['002_1.png', '002_2.png'],
#  ['003_1.png', '003_2.png', '003_3.png']]

阅读配方答案以了解更多细节。


1
漂亮的回答和点赞。我知道当你写了一个又长又正确的答案,却没有人点赞来认可你所投入的时间和精力时的感觉。 - Mihai Alexandru-Ionut
2
@MihaiAlexandru-Ionut 谢谢 :) 我无法忍受这个帖子中低文本/代码比率,所以我决定采取一些行动。你的答案是唯一一个有大量解释的答案。 - Aran-Fey

4

类似这样的内容应该可以正常工作:

import itertools


mylist = [...]
[list(v) for k,v in itertools.groupby(mylist, key=lambda x: x[:3])]

如果输入的列表没有排序,则需要使用类似以下方式的方法:
import itertools


mylist = [...]
keyfunc = lambda x:x[:3]
mylist = sorted(mylist, key=keyfunc)
[list(v) for k,v in itertools.groupby(mylist, key=keyfunc)]

1
你可以使用一个 字典 来完成它。
list = ['001_1.png', '001_2.png', '003_3.png', '002_1.png', '002_2.png', '003_1.png', '003_2.png', '003_3.png', '003_4.png']

dict = {}
for item in list:
  if item[:3] not in dict:
    dict[item[:3]] = []
  dict[item[:3]].append(item)

然后你需要按键值对字典进行排序。
dict = {k:v for k,v in sorted(dict.items())}

最后一步是使用列表推导式来实现您的要求。
list = [v for k,v in dict.items()]
print(list)

输出

[['001_1.png', '001_2.png'], ['002_1.png', '002_2.png'], ['003_3.png', '003_1.png', '003_2.png', '003_3.png', '003_4.png']]

0

使用简单的迭代和字典。

示例:

l = ['001_1.png', ' 001_2.png', ' 003_3.png', ' 002_1.png', ' 002_2.png', ' 003_1.png', ' 003_2.png', ' 003_3.png', ' 003_4.png']
r = {}
for i in l:
    v = i.split("_")[0][-1]
    if v not in r:
        r[v] = []
    r[v].append(i)
print(r.values())

输出:

[['001_1.png', ' 001_2.png'], [' 003_3.png', ' 003_1.png', ' 003_2.png', ' 003_3.png', ' 003_4.png'], [' 002_1.png', ' 002_2.png']]

0
如果您的列表是按照这种方式排序的,这里有一个简短的脚本可以完成此任务。
myList = []
for i in a:
    if i[:-4].endswith('1'):
        myList.append([i])
    else:
        myList[-1].append(i)

# [['001_1.png', '001_2.png', '003_3.png'], ['002_1.png', '002_2.png'], ...]

0
#IYN

mini_list = []
p = ['001_1.png', '001_2.png', '001_3.png', '002_1.png','002_2.png', '003_1.png', '003_2.png', '003_3.png', '003_4.png']
new_p = []

for index, element in enumerate(p):
    if index == len(p)-1:
        mini_list.append(element)
        new_p.append(mini_list)
        break

    if element[0:3]==p[index+1][0:3]:
        mini_list.append(element)

    else:
        mini_list.append(element)
        new_p.append(mini_list)
        mini_list = []

print (new_p)

上面的代码将把初始列表分割成子列表,并将它们作为单独的列表附加到一个更大的结果列表中。 注意:虽然不是几行代码,但你可以将其转换为一个函数。
def list_cutter(ls):
    mini_list = []
    new_list = []

    for index, element in enumerate(ls):
        if index == len(ls)-1:
            mini_list.append(element)
            new_list.append(mini_list)
            break

        if element[0:3]==ls[index+1][0:3]:
            mini_list.append(element)

        else:
            mini_list.append(element)
            new_list.append(mini_list)
            mini_list = []

    return new_list

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接