2013-12-05 2 views
0

Im пытается объединить два списка, которые имеют общую связь между ними (в этом случае это параметр id). у меня есть что-то вроде этого:Списки слияния Python по общему элементу

list1=[(id1,host1),(id2,host2),(id1,host5),(id3,host4),(id4,host6),(id5,host8)]

list2=[(id1,IP1),(id2,IP2),(id3,IP3),(id4,IP4),(id5,IP5)]

Хост является уникальным, но идентификатор в list1 может быть повторен, как вы можете видеть. Я хочу вывод, связывающую параметр id, что является обычным делом в обоих списках:

Некоторые выход, как:

IP1(host1,host5), IP2(host2), IP3(host4), IP4(host6), IP5(host8)

Как вы можете видеть, что IP1 имеет два хоста связаны.

Есть ли быстрый способ сделать это?

Спасибо

ответ

4
>>> from collections import defaultdict 
>>> list1 = [('id1','host1'),('id2','host2'),('id1','host5'),('id3','host4'),('id4','host6'),('id5','host8')] 
>>> list2 = [('id1','IP1'),('id2','IP2'),('id3','IP3'),('id4','IP4'),('id5','IP5')] 
>>> d1 = defaultdict(list) 
>>> for k,v in list1: 
...  d1[k].append(v) 
... 

Вы можете распечатать детали, как этот

>>> for k, s in list2: 
...  print s, d1[k] 
... 
IP1 ['host1', 'host5'] 
IP2 ['host2'] 
IP3 ['host4'] 
IP4 ['host6'] 
IP5 ['host8'] 

Вы можете использовать список понимание, чтобы поместить результаты в список

>>> res = [(s, d1[k]) for k, s in list2] 
>>> res 
[('IP1', ['host1', 'host5']), ('IP2', ['host2']), ('IP3', ['host4']), ('IP4', ['host6']), ('IP5', ['host8'])] 
1
  1. использования collections.defaultdict на карту id-> ip
  2. затем сопоставьте идентификатор -> IP
>>> d = defaultdict(set) 
>>> d['id'].add('host1') 
>>> d['id'].add('host2') 
>>> d['id'].add('host1') 
>>> d 
defaultdict(<type 'set'>, {'id': set(['host2', 'host1'])}) 
+0

Я думаю, что выход должен быть в том же порядке, что и list2 –

+0

@gnibbler получить идентификатор из списка2, затем искать в dict – linbo

0

Вы хотите, чтобы пройти через каждый из двух списков списков и добавить их содержимое в новый defaultdict с элементами типа list.

Это приведет к созданию словаря с содержанием, например {id1: (host1, host5), id2: host2, ...}.

Затем вы можете перечислить значения id в соответствии с их значениями IP.

Обратите внимание, что для того, чтобы это сработало, значения id должны быть hashable. Строки, числа и другие базовые типы хешируются.

Если значения id являются объектами определенного вами класса, вы можете наследовать этот класс из базового класса collections.Hashable.

1

Возможно, что-то вроде этого?

#!/usr/local/cpython-3.3/bin/python 

import pprint 
import collections 

class Host_data: 
    def __init__(self, ip_address, hostnames): 
     self.ip_address = ip_address 
     self.hostnames = hostnames 
     pass 

    def __str__(self): 
     return '{}({})'.format(self.ip_address, ','.join(self.hostnames)) 

    __repr__ = __str__ 

    # The python 2.x way 
    def __cmp__(self, other): 
     if self.ip_address < other.ip_address: 
      return -1 
     elif self.ip_address > other.ip_address: 
      return 1 
     else: 
      if self.hostnames < other.hostnames: 
       return -1 
      elif self.hostnames > other.hostnames: 
       return 1 
      else: 
       return 0 

    # The python 3.x way 
    def __lt__(self, other): 
     if self.__cmp__(other) < 0: 
      return True 
     else: 
      return False 


def main(): 
    list1=[('id1','host1'),('id2','host2'),('id1','host5'),('id3','host4'),('id4','host6'),('id5','host8')] 

    list2=[('id1','IP1'),('id2','IP2'),('id3','IP3'),('id4','IP4'),('id5','IP5')] 

    keys1 = set(tuple_[0] for tuple_ in list1) 
    keys2 = set(tuple_[0] for tuple_ in list2) 
    keys = keys1 | keys2 

    dict1 = collections.defaultdict(list) 
    dict2 = {} 

    for tuple_ in list1: 
     id_str = tuple_[0] 
     hostname = tuple_[1] 
     dict1[id_str].append(hostname) 

    for tuple_ in list2: 
     id_str = tuple_[0] 
     ip_address = tuple_[1] 
     dict2[id_str] = ip_address 

    result_dict = {} 
    for key in keys: 
     hostnames = [] 
     ip_address = '' 
     if key in dict1: 
      hostnames = dict1[key] 
     if key in dict2: 
      ip_address = dict2[key] 
     host_data = Host_data(ip_address, hostnames) 
     result_dict[key] = host_data 

    pprint.pprint(result_dict) 
    print('actual output:') 
    values = list(result_dict.values()) 
    values.sort() 
    print(', '.join(str(value) for value in values)) 

    print('desired output:') 
    print('IP1(host1,host5), IP2(host2), IP3(host4), IP4(host6), IP5(host8)') 


main() 
1

Код:

list1=[('id1','host1'),('id2','host2'),('id1','host5'),('id3','host4'),('id4','host6'),('id5','host8')] 
list1 = map(list,list1) 
list2=[('id1','IP1'),('id2','IP2'),('id3','IP3'),('id4','IP4'),('id5','IP5')] 
list2 = map(list,list2) 

for item in list1: 
    item += [x[1] for x in list2 if x[0]==item[0]] 

list1 += [x for x in list2 if not any(i for i in list1 if x[0]==i[0])] 

print list1 

Ouptut:

[['id1', 'host1', 'IP1'], ['id2', 'host2', 'IP2'], ['id1', 'host5', 'IP1'], ['id3', 'host4', 'IP3'], ['id4', 'host6', 'IP4'], ['id5', 'host8', 'IP5']] 

Надежда Это помогает :)

1
from collections import defaultdict 
list1 = [("id1","host1"),("id2","host2"),("id1","host5"),("id3","host4"),("id4","host6"),("id5","host8")] 
list2 = [("id1","IP1"),("id2","IP2"),("id3","IP3"),("id4","IP4"),("id5","IP5")] 
host = defaultdict(list) 
IP4id = {} 
for k, v in list2: 
    IP4id[v] = {"id" : k, "host" : []} 

for k, v in list1: 
    host[k].append(v) 

for item in IP4id: 
    IP4id[item]["host"] = host[IP4id[item]["id"]] 
print IP4id 
Смежные вопросы