2013-03-15 79 views
2

我有两个列表,可能具有不同的长度。每个列表都包含字符串形式的文件名。我无法控制名称,但我确信名称结构不会改变。它总是类似于name1_name2_number1 _ +(或 - )number2.jpg查找包含子字符串的两个列表中的元素

Number1是我想在两个列表之间匹配的子字符串。如果一个列表中的文件名包含与另一个列表中的文件名相同的number1,我想将这两个文件名追加到第三个列表中。我有一个简单的函数,将获得数字1在一个给定的列表,如:

>>>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功能和一些列表做理解,但是对于我来说,整体而言的'非常'是对我来说是新的,我不能完全理解这个。思考?建议?死亡威胁?感谢所有有用的回应,并且如果我的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))] 

我知道它的长和丑陋,但我真的想证明自己,这可能与列表理解来完成。感谢所有有用的回应!

+0

没有使用过多的map-reduce :) – GodMan 2013-03-15 19:24:53

回答

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的文件名,并从相应的索引抓取你想要的值。

+0

谢谢你给一个解决方案!我制作了GetNum是因为我们希望获得多个数字的确有可能。 – akimai 2013-03-15 19:19:39

1
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使用的发电机,以节省内存。由于数字可能不止一次匹配,我会继续检查每个项目。

+0

谢谢!我也想出了这个解决方案: '[m for list1 + list2 if any(s in m for s in GetNum(list1))and any(t in m for t in GetNum(list2))]' – akimai 2013-03-15 19:18:05

+0

@akimai更少的代码和pythonic,但更多的CPU和内存使用过程中。 – 2013-03-15 19:43:19

+0

我喜欢'pythonic'这个词如何被用来作为给定的一段代码的赞美和侮辱。^_^ – akimai 2013-03-15 20:01:19

0

我会为这两个列表建立一个字典,其中的关键字是文件名中的数字,值是文件名本身。那么,“相交”的两套钥匙的,所产生的公共密钥可以被用来建立第三个列表,e.g:

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] 
+1

该操作可以在列表中重复使用多个文件名。所以,不应该用这个 – GodMan 2013-03-15 19:09:11

+0

Danke GodMan!^_^ – akimai 2013-03-15 19:22:53

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 

编辑:拍,我现在看到你想要两个列表的交集。

+0

谢谢!^_^ – akimai 2013-03-15 19:22:30

+0

我已经改变它是对称的。 – Slumberheart 2013-03-15 20:15:01

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

为了清晰起见,你应该格式化一下。 – 2013-03-15 19:31:56

+0

格式化它。希望它现在看起来很干净。 – GodMan 2013-03-15 19:35:54

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'], []] 
相关问题