2

我有两个列表,可能长度不同。每个列表都包含字符串形式的文件名。我无法控制名称,但我确信名称结构不会改变。它总是类似于 name1_name2_number1_+(or-)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 ...]' 语法的精巧对我来说是新的,我不能完全包装我的绕过这个。想法?建议?死亡威胁?提前感谢所有有用的回复,如果我的 googlefu 未能让我尝试找到类似的问题/答案,我们深表歉意。

编辑 我刚刚想出了这个解决方案:

[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))]

我知道它又长又丑,但我真的想向自己证明它可以通过列表理解来完成。感谢所有有用的回复!

4

6 回答 6

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 中使用了一个生成器来节省内存。由于一个数字可能不止一次匹配,我会不断检查每个项目。

于 2013-03-15T18:56:43.463 回答
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.
于 2013-03-15T19:22:41.550 回答
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]
于 2013-03-15T19:08:35.410 回答
0

将字符串解析为您可以实际筛选的数据。那时事情会容易得多。

def process(filename):
    splitup = filename.rstrip('.jpg').split('_')
    keys = ["name1", "name2", "number1", "number2"]
    r = dict(zip(keys, splitup))
    r["filename"] = filename
    return r

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']

plist1 = [process(f) for f in list1]
plist2 = [process(f) for f in list2]

nlist1 = [i['number1'] for i in plist1]
nlist2 = [i['number1'] for i in plist2]

ilist1 = [i for i in plist1 if i['number1'] in nlist2]
ilist2 = [i for i in plist2 if i['number1'] in nlist1]

intersection = set([i["filename"] for i in ilist1 + ilist2])

for i in intersection:
    print i

编辑:射击,我现在看到你想要两个列表中的交叉点。

于 2013-03-15T19:09:29.357 回答
0

这将返回两个列表中所有匹配值的列表。例如,如果有数字 8000 和 300 的匹配项,它将为每个可能的数字返回一个完整的列表,然后仅使用匹配项填充列表。

list1 = ['serentity01_20malcolm_200_+3.jpg','inara03_kaley40_8000_-1.jpg',
         'inara03_34simon_300_+1.jpg']
list2 = ['inara03_summer40_8000_-2.jpg', 'book23_42jayne_400_+2.jpg',
         'summer53_21simon_300_-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]


print GetNum(list1)



def addToThird(input1, input2):

    numlist1 = GetNum(input1)
    numlist2 = GetNum(input2)

    numgroups = set(numlist1 + numlist2)
    numgroups = list(numgroups)
    collectionsList = []

    for i in numgroups:
    collectionsList.append([])

    for item1 in numlist1:
        for item2 in numlist2:
            if item1 == item2:
                print item1, item2
                goindex = numgroups.index(item1)
                collectionsList[goindex].append(input1[numlist1.index(item1)])
                collectionsList[goindex].append(input1[numlist2.index(item2)])
    return collectionsList


print addToThird(list1, list2)

输出:

['200', '8000', '300']
8000 8000
300 300
[['inara03_34simon_300_+1.jpg', 'inara03_34simon_300_+1.jpg'], [], 
'inara03_kaley40_8000_-1.jpg', 'serentity01_20malcolm_200_+3.jpg'], []]
于 2013-03-15T19:25:43.493 回答
0

未经测试,但逻辑应该是正确的:

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']
list3 = []

seenInList1Dict = {}

for element in list1:
    splitelem = element.split('_')
    seenInList1Dict[splitelem[2]] = 1

for element in list2:
    splitelem = element.split('_')
    if splitelem[2] in seenInList1Dict:
        list3.append(element)

我没有使用你的GetNum,因为它不必要地使 IMO 复杂化。如果您想稍后快速查找/比较它们的存在,我发现将它们转储到字典中会更容易。此外,如果您想要数字,您只需要对split文件名执行 a 并从相应的索引中获取您想要的值。

于 2013-03-15T18:56:31.793 回答