2012-02-02 90 views
1

假设我有一组包含人名的元组。我想找到大家谁分享相同的姓氏,排除人谁不向任何人透露自己的姓氏:查找具有公共元素的元组

# input 
names = set([('John', 'Lee'), ('Mary', 'Miller'), ('Paul', 'Ryan'), 
      ('Bob', 'Ryan'), ('Tina', 'Lee'), ('Bob', 'Smith')]) 

# expected output 
{'Lee': ['Tina', 'John'], 'Ryan': ['Bob', 'Paul']} # or similar 

这是我在用

def find_family(names): 
    result = {} 

    try: 
     while True: 
      name = names.pop() 
      if name[1] in result: 
       result[name[1]].append(name[0]) 
      else: 
       result[name[1]] = [name[0]] 
    except KeyError: 
     pass 

    return dict(filter(lambda x: len(x[1]) > 1, result.items())) 

这看起来丑陋和低效。有没有更好的办法?

回答

3

defaultdict可用于简化代码:

from collections import defaultdict 

def find_family(names): 
    d = defaultdict(list) 
    for fn, ln in names: 
     d[ln].append(fn) 
    return dict((k,v) for (k,v) in d.items() if len(v)>1) 

names = set([('John', 'Lee'), ('Mary', 'Miller'), ('Paul', 'Ryan'), 
      ('Bob', 'Ryan'), ('Tina', 'Lee'), ('Bob', 'Smith')]) 
print find_family(names) 

此打印:

{'Lee': ['Tina', 'John'], 'Ryan': ['Bob', 'Paul']} 
+0

(+1)这就是我要做的 – inspectorG4dget 2012-02-02 19:12:08

1

而不是使用一个while循环的,使用for循环(或类似的构建体)通过所述一组内容(当你在它,你可以解构元组):

for firstname, surname in names: 
    # do your stuff 

你可能想要使用defaultdictOrderedDict(http://docs.python.org/library/collections.html)将数据保存在循环体中。

+0

用一段时间遍历集合。我被推迟了。 – Aillyn 2012-02-02 19:13:42

+0

@Aillyn:我不会这么说,但这是一种你不得不以弱智语言使用的方法。 – Marcin 2012-02-02 19:16:13

1
>>> names = set([('John', 'Lee'), ('Mary', 'Miller'), ('Paul', 'Ryan'), 
...    ('Bob', 'Ryan'), ('Tina', 'Lee'), ('Bob', 'Smith')]) 

你可以得到所有的人的字典,其中键是他们的lastnames轻松地与一个for循环:

>>> families = {} 
>>> for name, lastname in names: 
... families[lastname] = families.get(lastname, []) + [name] 
... 
>>> families 
{'Miller': ['Mary'], 'Smith': ['Bob'], 'Lee': ['Tina', 'John'], 'Ryan': ['Bob', 'Paul']} 

然后,你只需要过滤字典的条件len(names) > 1。这个过滤可以使用“词典理解”来完成:

>>> filtered_families = {lastname: names for lastname, names in families.items() if len(names) > 1} 
>>> filtered_families 
{'Lee': ['Tina', 'John'], 'Ryan': ['Bob', 'Paul']}