在两个列表中查找包含子字符串的元素
我有两个列表,可能长度不一样。每个列表里都包含一些文件名,文件名的格式是字符串。我不能控制这些名字,但我知道它们的结构不会改变。它们总是像这样:name1_name2_number1_+(或-)number2.jpg
其中,number1是我想在两个列表中匹配的部分。如果一个列表中的文件名包含与另一个列表中相同的number1,我想把这两个文件名都加到第三个列表里。我有一个简单的函数可以从给定的列表中获取number1,比如:
>>>list1 = ['serentity01_20malcolm_200_+3.jpg','inara03_kaley40_8000_-1.jpg']
>>>def GetNum(imgStrings):
... ss = []
... for b in imgStrings:
... ss.append([w for w in b.split('_') if w.isdigit()])
... #flatten zee list of lists because it is ugly.
... return [val for subl in ss for val in subl]
>>>GetNum(list1)
['200', '800]
所以,对于
>>>list1 = ['serentity01_20malcolm_200_+3.jpg','inara03_kaley40_8000_-1.jpg']
>>>list2 = ['inara03_summer40_8000_-2.jpg', 'book23_42jayne_400_+2.jpg', 'summer53_21simon_300_-1.jpg']
>>>awesomesauceSubstringMatcher(list1, list2)
['inara03_kaley40_8000_-1.jpg', 'inara03_summer40_8000_-2.jpg']
我觉得我应该能用我的GetNum函数和一些列表推导来做到这一点,但整个'[blah for blah in ...]'的语法对我来说是新的,我有点搞不明白。有什么想法?建议?威胁?感谢所有提前提供帮助的回复,如果我在寻找类似问题/答案时没有找到,真是万分抱歉。
编辑
我刚刚想出了这个解决方案:
[str for str in list1+list2 if any(subs in str for subs in GetNum(list1)) and any(subs in str for subs in GetNum(list2))]
我知道这段代码很长也很丑,但我真的想证明自己可以用列表推导来实现。感谢所有的帮助!
6 个回答
0
My bit of the solution using map,reduce, filter and list flattening using sum:-
l=['a_b_1_2','b_c_2_3']
s=['c_d_3_4','d_e_1_4']
a=map(lambda y: map(lambda z: [y,z] if y[2] == z[2] else '', map(lambda v:v.split('_'), s)),map(lambda x:x.split('_'),l))
map(lambda x: '_'.join(x), sum(filter(lambda qq: qq is not '',sum(a,[]))))
在实际的数据集上展示:
>>> list1 = ['serentity01_20malcolm_200_+3.jpg','inara03_kaley40_8000_-1.jpg']
>>> list2 = ['inara03_summer40_8000_-2.jpg', 'book23_42jayne_400_+2.jpg', 'summer53_21simon_300_-1.jpg']
>>> a=map(lambda y: map(lambda z: [y,z] if y[2] == z[2] else '', map(lambda v:v.split('_'), list2)),map(lambda x:x.split('_'),list1))
>>> a
[['', '', ''], [[['inara03', 'kaley40', '8000', '-1.jpg'], ['inara03', 'summer40', '8000', '-2.jpg']], '', '']]
>>> sum(filter(lambda qq: qq is not '',sum(a,[])),[])
[['inara03', 'kaley40', '8000', '-1.jpg'], ['inara03', 'summer40', '8000', '-2.jpg']]
>>> map(lambda x: '_'.join(x), sum(filter(lambda qq: qq is not '',sum(a,[])),[]))
['inara03_kaley40_8000_-1.jpg', 'inara03_summer40_8000_-2.jpg'] #This is the output you want.
0
我会为这两个列表建立一个字典,字典的“键”是文件名中的数字,而“值”就是文件名本身。接着,我会找出这两个字典中共同的键,也就是两个列表中都有的数字。然后可以用这些共同的键来创建第三个列表,比如:
def List2Dic(List):
return dict(map(lambda x: [ x.split("_")[2], x], List))
list1 = ['serentity01_20malcolm_200_+3.jpg','inara03_kaley40_8000_-1.jpg']
list2 = ['inara03_summer40_8000_-2.jpg', 'book23_42jayne_400_+2.jpg', 'summer53_21simon_300_-1.jpg']
d1 = List2Dic(list1)
d2 = List2Dic(list2)
for x in set(d1) & set(d2):
print d1[x], d2[x]
2
list1 = ['serentity01_20malcolm_200_+3.jpg','inara03_kaley40_8000_-1.jpg']
list2 = ['inara03_summer40_8000_-2.jpg', 'book23_42jayne_400_+2.jpg', 'summer53_21simon_300_-1.jpg']
def getNum(image_name_list):
for s in image_name_list:
s = s.split('_')[2]
if s.isdigit():
yield s
else:
yield None
def getMatchingIndex(list1, list2):
other_list = list(getNum(list2))
for (i, num) in enumerate(getNum(list1)):
if not num:
continue
for (j, other_num) in enumerate(getNum(list2)):
if (num == other_num):
yield (i, j)
for i1, i2 in getMatchingIndex(list1, list2):
print list1[i1], list2[i2]
因为我们只需要把一个项目和第二个列表里的每个项目逐个比较,所以我在getNum里用了生成器来节省内存。由于一个数字可能会匹配多次,我会继续检查每个项目。