基于键的唯一dicts列表

时间:2010-12-06 20:31:03

标签: python dictionary

我有一个dics列表:

     data = {}
     data['key'] = pointer_key
     data['timestamp'] = timestamp
     data['action'] = action
     data['type'] = type
     data['id'] = id

     list = [data1, data2, data3, ... ]

如何确保对于列表中的每个数据项,每个“密钥”只存在一个这样的元素?如果有如下所示的两个键,则最近的时间戳将获胜:

    list = [{'key':1,'timestamp':1234567890,'action':'like','type':'photo',id:245},
            {'key':2,'timestamp':2345678901,'action':'like','type':'photo',id:252},
            {'key':1,'timestamp':3456789012,'action':'like','type':'photo',id:212}]

    unique(list)

    list = [{'key':2,'timestamp':2345678901,'action':'like','type':'photo',id:252},
            {'key':1,'timestamp':3456789012,'action':'like','type':'photo',id:212}]

感谢。

10 个答案:

答案 0 :(得分:4)

这是我的解决方案:

def uniq(list_dicts):
    return [dict(p) for p in set(tuple(i.items()) 
        for i in list_dicts)]
希望它会对某人有所帮助。

答案 1 :(得分:3)

我需要这个,但不喜欢这里的任何答案。所以我制作了这个简单且高性能的版本。

def list_of_seq_unique_by_key(seq, key):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if x[key] not in seen and not seen_add(x[key])]

# Usage
# If you want most recent timestamp to win, just sort by timestamp first
list = sorted(list, key=lambda k: k['timestamp'], reverse=True)
# Remove everything with a duplicate value for key 'key'
list = list_of_seq_unique_by_key(list, 'key')

答案 2 :(得分:1)

为了澄清,您有多个词典,但是您想要一个独特的数据['key']?例如,如果data1 ['key'] ='hello',你想确保不允许data2 ['key'] ='hello'?你想要它只是引发错误吗?这是验证其罚款的一种方法。 (将列表'列表'命名为列表是python中的数据类型<)>

datalist = [datadict1, datadict2, datadict3]
big_key_list = []
for datadict in datalist:
    curkey = datadict.get('key')
    if curkey not in big_key_list:
        big_key_list.append(curkey)
    else:
        raise Exception("Key %s in two data dicts" % curkey)

现在更好的方法是创建一个继承自包含子句的dict的新类,但不允许多个键具有相同的值。这样就可以在分配时抛出错误,而不是只检查事情是否正常(如果事情不好就不知道该怎么办,除了引发错误)。

编辑: 实际上,看看你可能想做什么,你的数据设置不正确。我这样说,因为看起来你想为每个条目都有一个单独的字典。这几乎可以肯定是一种不太优雅的方式。

首先创建一个类:

class MyDataObject(object):
    def __init__(self, **kwargs):
        for k,v in kwargs:
            self.__dict__[k] = v

或者如果他们总是拥有所有4个固定参数:

class MyDataObject(object):
    def __init__(self, timestamp, action, obj_type, obj_id):
        self.timestamp = timestamp
        self.action = action
        self.type = obj_type
        self.id = obj_id

然后只定义您的数据类型。

data = {}
data['key1'] = MyDataObject(timestamp='some timestamp', action='some action', type='some type', id = 1234)
data['key2'] = MyDataObject(timestamp='some timestamp2', action='some action2', type='some type2', id = 1235)

您可以访问以下数据:

data['key1'].timestamp # returns 'some timestamp'
data['key2'].action # returns 'some action2'

或者您甚至可以使用 dict ()进行访问(例如,如果您有变量x ='action'并且想要访问它,这会很有用。)

data['key1'].__dict__('action') # returns 'some action'
data['key2'].__dict__('timestamp') # returns 'some timestamp2'

现在你只有一个对象字典,其中键是唯一的,与键相关的数据保存为一个对象(MyDataObject类型)。

答案 3 :(得分:1)

我认为你的意思是每个'key'字段对所有数据都应该是唯一的。

好吧,让我们从你应该做的事情开始:使用数据库,他们喜欢解决这些问题。

你也可以手工完成这项工作,例如:

def unique_keys( items):
    seen = set()
    for item in items:
        key = item['key']
        if key not in seen:
             seen.add(key)
             yield item
        else:
             # its a duplicate key, do what?
             pass # drops it

print list(unique_keys(data_list))

或许你想要一个存储现有密钥的数据结构,并阻止你为已经存在的密钥创建新的数据......?

答案 4 :(得分:1)

您还可以使用列表字典,每个列表位置代表一个特定值。

data = {}
data[pointer_key] = [timestamp, action, type, id]
if new_pointer_key in data:
    if this_timestamp > data[new_pointer_key][0]:   ## first element of list=timestamp
        data[new_pointer_key] = [new_timestamp,  new_action, new_type, new_id] 

答案 5 :(得分:0)

你不需要。根据定义,dict只能有一个给定键的条目。

答案 6 :(得分:0)

>>> d = {'a': 1, 'b': 2, 'a': 3}
>>> d
{'a': 3, 'b': 2}

所以在一个词典中,关键是唯一的。

更新:(根据您的评论)

如果您要查找一个键,多个值,则将dict子类化为:

>>> class custom_dict(dict):
      def __setitem__(self, key, value):
        self.setdefault(key, []).append(value)

>>> m = custom_dict()
>>> m['key'] = 1
>>> m['key'] = 2
>>> m
{'key': [1, 2]}

应该这样做。

答案 7 :(得分:0)

当你做这些事情的时候,这通常是一个很好的迹象,表明某处的设计存在错误 但它可以做到:

from operator import itemgetter

def unique(list_of_dicts):
    _sorted = sorted(list_of_dicts, key=itemgetter('timestamp'), reverse=True)
    known_keys = set()
    result = []
    for d in _sorted:
        key = d['key']
        if key in known_keys: continue
        known_keys.add(key)
        result.append(d)
    return result

输出(注意:它改变了排序):

[{'action': 'like', 'timestamp': 3456789012, 'type': 'photo', 'id': 212, 'key': 1},
{'action': 'like', 'timestamp': 2345678901, 'type': 'photo', 'id': 252, 'key': 2}]

现在密钥是唯一的(根据需要保留最近的时间戳),最好将其转换为更好地反映数据的内容,as suggested by jimbob

class MyDataObject(object):
    def __init__(self, timestamp, action, obj_type, obj_id):
        self.timestamp = timestamp
        self.action = action
        self.type = obj_type
        self.id = obj_id

data = {}
for action in unique(_list):
    key = action['key']
    data[key] = MyDataObject(action['timestamp'], action['action'],
        action['type'], action['id'])

答案 8 :(得分:0)

itertools中的groupby函数在这里可能很有用:

def unique(items, key, order=None):
    sort_func = (lambda v: (key(v), order(v))) if order else key
    groups = itertools.groupby(sorted(items, key=sort_func), key)
    return [group.next() for unused_key, group in groups]

def unique(items, key, order=None):
    groups = itertools.groupby(sorted(items, key=key), key)
    return [max(group, key=order) for unused_key, group in groups]

它将基于可选键显示相同的项目组合在一起。在由相同限定符排序的数据上使用它将把它们分组。采用第一个元素将使它们独一无二。允许您按时间戳排序&#39;选项,我们可以按键和时间戳排序,然后只按键分组。然后你可以使用它如下:

data = [{'key':1, 'timestamp':1234567890, 'action':'like', 'type':'photo', 'id':245},
        {'key':2, 'timestamp':2345678901, 'action':'like', 'type':'photo', 'id':252},
        {'key':1, 'timestamp':3456789012, 'action':'like', 'type':'photo', 'id':212}]

# unique(data)
key = lambda d: d['key']  # Group by key
order = lambda d: -d['timestamp']  # Sort by descending order timestamp
data = unique(data, key, order_func=order)

data == [{'key':1, 'timestamp':3456789012, 'action':'like', 'type':'photo', 'id':212},
         {'key':2, 'timestamp':2345678901, 'action':'like', 'type':'photo', 'id':252}]

我们强制键在sort函数中排在第一位,以确保我们正确分组,无论顺序如何。

此解决方案会更改商品的顺序,但它确实具有无害存储和时间复杂性的优势。

答案 9 :(得分:0)

var string = "[4]Motherboard, [25]RAM",
    data = string.split(', ').map(function (a) {
        var p = a.match(/^\[(\d+)\](.+)$/);
        return { id: p[1], item: p[2] };
    });
console.log(data);
相关问题