python - 如何根据匹配的子字符串从一个列表创建多个列表?

标签 python python-3.x list substring

我在 python 中有一个由各种文件名组成的字符串列表,如下所示(但更长):

all_templates = ['fitting_file_expdisk_cutout-IMG-HSC-I-18115-6,3-OBJ-NEP175857.9+655841.2.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-3,3- OBJ-NEP180508.6+655617.3.feedme','fitting_file_sersic_cutout-IMG-HSC-I-18115-1,8-OBJ-NEP180840.8+665226.2.feedme','fitting_file_sersic_cutout-IMG-HSC-I-18115-6, 7-OBJ-NEP175927.6+664230.2.feedme'、'fitting_file_expdisk_cutout-IMG-HSC-I-18114-0,5-OBJ-zsel56238.feedme'、'fitting_file_devauc_cutout-IMG-HSC-I-18114-0,3- OBJ-NEP175616.1+660601.5.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-6,4-OBJ-zsel56238.feedme']

我想为具有相同对象名称的元素创建多个较小的列表(以 OBJ- 开头并在 .feedme 之前结束的子字符串)。所以我会有一个这样的列表:

obj1 = ['fitting_file_expdisk_cutout-IMG-HSC-I-18114-0,5-OBJ-zsel56238.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-6,4-OBJ-zsel56238。 feedme'],

对于其他匹配的“对象”依此类推。实际上,我有超过 900 个独特的“对象”,原始列表 all_templates 有超过 4000 个元素,因为每个对象都有 3 个或更多单独的模板文件(它们都以随机顺序开始)。所以最后我想要超过 900 个列表(每个对象一个)。我怎样才能做到这一点?

编辑:这是我尝试过的,但它为我提供了每个子列表中所有原始模板文件名的列表(每个子列表对于一个对象名称都应该是唯一的)。

import re
# Break up list into multiple lists according to substring (object name)
obj_list = [re.search(r'.*(OBJ.+)\.feedme', filename)[1] for filename in all_template_files]
obj_list = list(set(obj_list)) # create list of unique objects (remove duplicates)

templates_objs_sorted = [[]]*len(obj_list)
for i in range(len(obj_list)):
    for template in all_template_files:
        if obj_list[i] in template:
            templates_objs_sorted[i].append(template)

最佳答案

from collections import defaultdict
from pprint import pprint

all_templates = ['fitting_file_expdisk_cutout-IMG-HSC-I-18115-6,3-OBJ-NEP175857.9+655841.2.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-3,3-OBJ-NEP180508.6+655617.3.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-1,8-OBJ-NEP180840.8+665226.2.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-6,7-OBJ-NEP175927.6+664230.2.feedme', 'fitting_file_expdisk_cutout-IMG-HSC-I-18114-0,5-OBJ-zsel56238.feedme', 'fitting_file_devauc_cutout-IMG-HSC-I-18114-0,3-OBJ-NEP175616.1+660601.5.feedme', 'fitting_file_sersic_cutout-IMG-HSC-I-18115-6,4-OBJ-zsel56238.feedme']

# simple helper function to extract the common object name
# you could probably use Regex... but then you'd have 2 problems
def objectName(path):
    start = path.index('-OBJ-')
    stop = path.index('.feedme')
    return path[(start + 5):stop]

# I really wanted to use a one line reduce here, but... 
grouped = defaultdict(list)
for each in all_templates:
    grouped[objectName(each)].append(each)
pprint(grouped)

旁白/切线

好吧,我无法使用reduce做一个简单的衬里,这真的让我很烦恼。那里。最后祝愿python过得好groupby功能。它具有同名的功能,但仅限于连续键。 Smalltalk、Objc 和 Swift 都有 groupby 机制,基本上允许您通过任意传输函数对 utterable 进行分桶。

我最初的尝试如下:

grouped = reduce(
    lambda accum, each: accum[objectName(each)].append(each),
    all_templates,
    defaultdict(list))

问题出在 lambda 上。 lambda 仅限于单个表达式。为了让它在reduce中工作,它大多数会返回累积参数的修改版本。但是 python 不喜欢从函数/方法返回东西,除非必须这样做。即使我们更换了 append<accessTheCurrentList> + [each] ,我们需要一个字典修改方法来更新键上的值并返回修改后的字典。我找不到这样的东西。

但是,我们可以做的是将更多信息加载到累加器中,例如元组。我们可以使用元组的一个槽来继续传递 defaultdict 指针,另一个槽来捕获修改操作的无用 None 返回。它最终变得相当丑陋,但它是一行:

from functools import reduce
grouped = reduce(
    lambda accum, each: (accum[0], accum[0][objectName(each)].append(each)),
    all_templates,
    (defaultdict(list), None))[0]

关于python - 如何根据匹配的子字符串从一个列表创建多个列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54337537/

相关文章:

python - 如果一列的元素是非数字的,则删除 pandas dataframe 行

python - 在 Dataframe 中查找重复项并返回 1 和 0

list - 涉及列表操作的 Lisp 练习

python - 在 Python 中存储和访问大型(~10 GB)列表的方法?

python - 导入错误 : couldn't find library

python - 使用 PyGObject 自省(introspection)编写 MATE/GNOME 小程序 (Python)

python - 最常见单词或短语的 FreqDist

python - 如果任何列包含关键字之一,则删除行

python - 我需要在哪里放置我的 Django 测试以便它们被执行?

python - 循环处理列表中的项目,重新循环直到处理完所有项目