2013-03-15 77 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'], []] 
相關問題