【问题标题】:Sort a list of dictionaries while consolidating duplicates in Python?在 Python 中合并重复项时对字典列表进行排序?
【发布时间】:2013-08-30 16:29:41
【问题描述】:

所以我有一个这样的字典列表:

data = [ { 
           'Organization' : '123 Solar',
           'Phone' : '444-444-4444',
           'Email' : '',
           'website' : 'www.123solar.com'
         }, {
           'Organization' : '123 Solar',
           'Phone' : '',
           'Email' : 'joey@123solar.com',
           'Website' : 'www.123solar.com'
         }, {
           etc...
         } ]

当然,这不是确切的数据。但是(也许)从我这里的例子中你可以发现我的问题。我有许多具有相同“组织”名称的记录,但其中没有一条具有该记录的完整信息。

有没有一种高效的方法来搜索列表,根据字典的第一个条目对列表进行排序,最后合并重复数据以创建一个唯一条目? (请记住,这些字典非常大)

【问题讨论】:

    标签: python sorting search python-2.7 merge


    【解决方案1】:

    您可以使用itertools.groupby:

    from itertools import groupby
    from operator import itemgetter
    from pprint import pprint
    
    data = [ {
               'Organization' : '123 Solar',
               'Phone' : '444-444-4444',
               'Email' : '',
               'website' : 'www.123solar.com'
             }, {
               'Organization' : '123 Solar',
               'Phone' : '',
               'Email' : 'joey@123solar.com',
               'Website' : 'www.123solar.com'
             },
             {
               'Organization' : '234 test',
               'Phone' : '111',
               'Email' : 'a@123solar.com',
               'Website' : 'b.123solar.com'
             },
             {
               'Organization' : '234 test',
               'Phone' : '222',
               'Email' : 'ac@123solar.com',
               'Website' : 'bd.123solar.com'
             }]
    
    
    data = sorted(data, key=itemgetter('Organization'))
    result = {}
    for key, group in groupby(data, key=itemgetter('Organization')):
        result[key] = [item for item in group]
    
    pprint(result)
    

    打印:

    {'123 Solar': [{'Email': '',
                    'Organization': '123 Solar',
                    'Phone': '444-444-4444',
                    'website': 'www.123solar.com'},
                   {'Email': 'joey@123solar.com',
                    'Organization': '123 Solar',
                    'Phone': '',
                    'Website': 'www.123solar.com'}],
     '234 test': [{'Email': 'a@123solar.com',
                   'Organization': '234 test',
                   'Phone': '111',
                   'Website': 'b.123solar.com'},
                  {'Email': 'ac@123solar.com',
                   'Organization': '234 test',
                   'Phone': '222',
                   'Website': 'bd.123solar.com'}]}
    

    更新:

    以下是将项目分组到单个字典中的方法:

    for key, group in groupby(data, key=itemgetter('Organization')):
        result[key] = {'Phone': [],
                       'Email': [],
                       'Website': []}
        for item in group:
            result[key]['Phone'].append(item['Phone'])
            result[key]['Email'].append(item['Email'])
            result[key]['Website'].append(item['Website'])
    

    那么,在result 你将拥有:

    {'123 Solar': {'Email': ['', 'joey@123solar.com'],
                   'Phone': ['444-444-4444', ''],
                   'Website': ['www.123solar.com', 'www.123solar.com']},
     '234 test': {'Email': ['a@123solar.com', 'ac@123solar.com'],
                  'Phone': ['111', '222'],
                  'Website': ['b.123solar.com', 'bd.123solar.com']}}
    

    【讨论】:

    • 我测试了你的代码,但它并不是我所需要的。感谢您向我展示这种类型,这太棒了。我正在寻找一种方法将具有相同组织名称的所有字典组合到同一个列表中的一个字典中。
    • 当然,您可以从中制作一本字典。只需使用 group 变量即可。
    【解决方案2】:

    是否有一种有效的方法来搜索列表,根据字典的第一个条目对列表进行排序,最后合并重复项中的数据以创建唯一条目?

    是的,但有一种更有效的方法,无需搜索和排序。边做边建立字典:

    datadict = {}
    for thingy in data:
        organization = thingy['Organization']
        datadict[organization] = merge(thingy, datadict.get(organization, {}))
    

    现在您已经对数据进行了线性传递,对每个数据进行了恒定时间查找。因此,它比任何排序的解决方案都要好 O(log N) 倍。它也是一次传递而不是多次传递,而且它可能具有更低的常量开销。


    目前尚不清楚您要合并条目的确切操作,并且任何人都无法在不知道您要使用什么规则的情况下编写代码。但这里有一个简单的例子:

    def merge(d1, d2):
        for key, value in d2.items():
            if not d1.get(key):
                d1[key] = value
        return d1
    

    换句话说,对于d2 中的每一项,如果d1 已经有一个真值(如非空字符串),则不管它;否则,添加它。

    【讨论】:

    • 你对merge函数有什么建议吗?
    • 这是最简单的部分;我假设你已经知道如何做到这一点。但我将编辑答案以显示一个示例:
    • 我是 Python 新手..对不起,如果我看起来很笨。
    猜你喜欢
    • 2015-12-26
    • 1970-01-01
    • 2011-12-22
    • 2016-06-11
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 2016-02-26
    相关资源
    最近更新 更多