在两个列表中查找包含子字符串的元素

2 投票
6 回答
1999 浏览
提问于 2025-04-17 19:15

我有两个列表,可能长度不一样。每个列表里都包含一些文件名,文件名的格式是字符串。我不能控制这些名字,但我知道它们的结构不会改变。它们总是像这样: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里用了生成器来节省内存。由于一个数字可能会匹配多次,我会继续检查每个项目。

撰写回答