我在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)
答案 0 :(得分:1)
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机制,这些机制基本上使您可以通过任意传递函数来存储可说话的东西。
我最初的尝试是:
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]
答案 1 :(得分:0)
您可以对排序列表进行分组:
from itertools import groupby
import re
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']
pattern = re.compile(r'OBJ-.*?\.feedme$')
objs = {name: pattern.search(name)[0] for name in all_templates}
result = [list(g) for k, g in groupby(sorted(all_templates, key=objs.get), key=objs.get)]
print(result)
输出:
[['fitting_file_devauc_cutout-IMG-HSC-I-18114-0,3-OBJ-NEP175616.1+660601.5.feedme'],
['fitting_file_expdisk_cutout-IMG-HSC-I-18115-6,3-OBJ-NEP175857.9+655841.2.feedme'],
['fitting_file_sersic_cutout-IMG-HSC-I-18115-6,7-OBJ-NEP175927.6+664230.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_expdisk_cutout-IMG-HSC-I-18114-0,5-OBJ-zsel56238.feedme',
'fitting_file_sersic_cutout-IMG-HSC-I-18115-6,4-OBJ-zsel56238.feedme']]
答案 2 :(得分:0)
使用regular expression
方法,因此需要
import re
鉴于文件名列表,我对其进行了自定义以显示结果:
all_templates = ['aaa-OBJ-NEP175857.9+655841.2.feedme',
'bbb-OBJ-NEP175857.9+655841.2.feedme',
'ccc-OBJ-NEP175857.9+655841.2.feedme',
'ddd-OBJ-whathever.feedme',
'eee-OBJ-whathever.feedme',
'fff-SUBJ-whathever.feedme',
'fff-OBJ.feedme'
]
这可以是一个选择:
result = {}
for filename in all_templates:
match = re.search('OBJ-(.+?).feedme', filename)
if match:
result.setdefault(match.group(1), list()).append(filename)
else:
result.setdefault('no-match', list()).append(filename)
它使用OBJ-
和.feedme
之间的子字符串作为字典的键,并附加具有相同子字符串的每个文件名。如果没有匹配项,它将使用“ no-match”来附加不匹配搜索的子字符串。
因此,它返回:
print(result)
# {'NEP175857.9+655841.2': ['aaa-OBJ-NEP175857.9+655841.2.feedme', 'bbb-OBJ-NEP175857.9+655841.2.feedme', 'ccc-OBJ-NEP175857.9+655841.2.feedme'],
# 'whathever': ['ddd-OBJ-whathever.feedme', 'eee-OBJ-whathever.feedme'],
# 'no-match': ['fff-SUBJ-whathever.feedme', 'fff-OBJ.feedme']}
如果仅需要组列表:
list(result.values())