2012-11-17 55 views
1

我有以下兩個列表:的Python:比較列表和在共同領域的結合

ISO3166_CountryCodes_NO = [["NO","Norge"],["SE","Sverige"],["GR","Hellas"]] 
ISO3166_CountryCodes_EN = [["NO","Norway"],["SE","Sweden"],["GR","Greece"]] 

正如你看到的,國家代碼始終是相同的,但該國名稱不同(不同的譯本) 如何能我創建一個列表如下:

ISO3166_CountryCodes = [["NO","Norge","Norway"],["SE","Sverige","Sweden"],["GR","Hellas","Greece"]] 

我可以用它做在第一列表循環,對於每個元素我可以搜索到第二個,找到國家代碼是常見的。然後將譯文附加到新列表中,但我覺得這種方式有點笨拙。

有沒有更好的方法在Python中實現這一點?例如在我更熟悉的Perl中,我會使用一個哈希表。

回答

4

在Python中,詞典是一個哈希表。首先,創建兩個字典:

NO_dict = {x[0]: x[1] for x in ISO3166_CountryCodes_NO} 
EN_dict = {x[0]: x[1] for x in ISO3166_CountryCodes_EN} 

它給你:

{'GR': 'Hellas', 'NO': 'Norge', 'SE': 'Sverige'} 
{'GR': 'Greece', 'NO': 'Norway', 'SE': 'Sweden'} 

然後,您可以創建一個列表,像這樣:

final_list = [[k, NO_dict[k], EN_dict[k]] for k in NO_dict] 

給你:

[['GR', 'Hellas', 'Greece'], 
['SE', 'Sverige', 'Sweden'], 
['NO', 'Norge', 'Norway']] 

你可能會稍後發現保持這種狀態與

final_dict = {k:(NO_dict[k], EN_dict[k]) for k in NO_dict} 

所以,你可以使用縮寫爲關鍵例如抓取物品存放在元組的名稱,例如:a詞典ê數據final_dict['NO']會產生('Norge', 'Norway')

編輯:OrderedDict

如果你有蟒蛇> = 2.7,而你所關心的順序,你仍然可以通過OrderedDict,例如使用字典:

from collections import OrderedDict 

# A list of lists can be used as input for an OrderedDict, so don't need to loop 
NO_dict = OrderedDict(ISO3166_CountryCodes_NO) 
EN_dict = OrderedDict(ISO3166_CountryCodes_EN) 

# Assumes you want the result in the same order as the Norwegian list 
# Iterate over the English list if it has a preferred order 

final_dict = OrderedDict([(k, (NO_dict[k], EN_dict[k])) for k in NO_dict]) 

(關於另一個實現,請參閱AshwiniChaudhary的答案)

+2

請注意,這個答案和Ashwini的答案在涉及允許的輸入和結果輸出時有兩個區別:即使國家/地區的順序在列表之間不同,但此方案(自然地)也不保留此順序解決方案。 –

+0

謝謝!非常乾淨,簡短的代碼和易於理解:) –

+1

@lazyr增加了一個解決方案,即使列表是隨機排列的,也保留了順序。 –

2

這樣的事情,使用unique_everseenitertools recipeschain()

In [26]: from itertools import * 

In [27]: lis1=[["NO","Norge"],["SE","Sverige"],["GR","Hellas"]] 

In [28]: lis2=[["NO","Norway"],["SE","Sweden"],["GR","Greece"]] 

In [29]: from itertools import * 

In [30]: def unique_everseen(iterable, key=None): 
     seen = set() 
     seen_add = seen.add 
     if key is None: 
       for element in ifilterfalse(seen.__contains__, iterable): 
         seen_add(element) 
         yield element 
       else: 
         for element in iterable: 
           k = key(element) 
           if k not in seen: 
             seen_add(k) 
             yield element 
    ....:       

In [31]: [list(unique_everseen(chain(*x))) for x in izip(lis1,lis2)] 
Out[31]: 
[['NO', 'Norge', 'Norway'], 
['SE', 'Sverige', 'Sweden'], 
['GR', 'Hellas', 'Greece']] 

或:可以使用groupby從itertools,與operator.itemgetter()結合:

In [42]: from operator import * 

In [43]: [[k]+list(map(itemgetter(1),g)) for x in zip(lis1,lis2) for k,g in groupby(x,itemgetter(0))] 
Out[43]: 
[['NO', 'Norge', 'Norway'], 
['SE', 'Sverige', 'Sweden'], 
['GR', 'Hellas', 'Greece']] 

或使用collections.OrderedDict,這是dict的子類別並維護順序:

In [47]: from collections import OrderedDict 

In [48]: dic=OrderedDict() 

In [49]: for x in lis1: 
    ....:  dic.setdefault(x[0],[]).append(x[1]) 
    ....:  

In [50]: for x in lis2: 
    dic.setdefault(x[0],[]).append(x[1]) 
    ....:  

In [51]: dic 
Out[51]: OrderedDict([('NO', ['Norge', 'Norway']), ('SE', ['Sverige', 'Sweden']), ('GR', ['Hellas', 'Greece'])]) 

In [52]: [[x]+y for x,y in dic.items()] 
Out[52]: 
[['NO', 'Norge', 'Norway'], 
['SE', 'Sverige', 'Sweden'], 
['GR', 'Hellas', 'Greece']] 

#or directly access the names using the short-name 
In [53]: dic['NO'] 
Out[53]: ['Norge', 'Norway'] 

In [54]: dic['GR'] 
Out[54]: ['Hellas', 'Greece'] 
+0

謝謝你的許多選擇! –

+0

@VangelisTasoulas不客氣,你可以upvote或標記答案爲接受,如果你覺得有幫助,我認爲這是正確的方式說SO感謝。 –

1

你可以使用列表理解:

>>> [[s]+ 
    [n for (c,n) in ISO3166_CountryCodes_NO if c==s]+ 
    [n for (c,n) in ISO3166_CountryCodes_EN if c==s] 
    for s in set([c for (c,n) in ISO3166_CountryCodes_NO] + 
        [c for (c,n) in ISO3166_CountryCodes_EN])] 

[['GR', 'Hellas', 'Greece'], ['SE', 'Sverige', 'Sweden'], ['NO', 'Norge', 'Norway']] 
1

使用Python 3.2。

1路:

[[i[0],i[1],v[1]] for i in list1 for v in list2 if i[0]==v[0]] 

第二個辦法:

res=[] 
for i,v in list(zip(list1,list2): 
    tem=[i[0]] 
    if i[0]==v[0]: tem.extend([i[1],v[1]]) 
res.append(tem) 
+0

請僅使用代碼段的代碼格式,而不是您的整個答案。有關更多格式選項,請參閱http://stackoverflow.com/editing-help –