在Python中

时间:2018-04-09 14:51:02

标签: python dictionary optimization lambda

我正在寻找解决以下问题的最有效/蟒蛇方式:

我有一个本地对象列表(list_a),一个服务器上的对象列表(list_b)。 list_b是字典列表,而不是对象。 我想用服务器给出的信息更新本地对象中的一些信息。可以通过字典中的属性name或标识符'name'来完成分配。两个列表都可以是彼此的子集。

以下是我当前的解决方案,其中包含一些示例数据:

class Dummy():
    def __init__(self, name):
        self._name = name
        self._attr = ''

    def __str__(self):
        return "Test-Object[" + self._name + ", " + self._attr + "]"

    def update(self, obj):
        self._attr = obj['attr']

    __repr__ = __str__

list_a = [Dummy(str(x)) for x in xrange(10)] 
list_b = [{'name': str(x), 'attr': str(x*2)} for x in xrange(8, -1, -1)] 

extracted_names_a = [x._name for x in list_a]
extracted_names_b = [x['name'] for x in list_b]
filtered_list_a = (x for x in list_a if x._name in extracted_names_b)
filtered_list_b = (x for x in list_b if x['name'] in extracted_names_a)
sorted_list_a = sorted(filtered_list_a, key=lambda k: k._name)
sorted_list_b = sorted(filtered_list_b, key=lambda k: k['name'])
for obj, d in zip(sorted_list_a, sorted_list_b):
    obj.update(d)

print(list_a)

这只是一个简单的例子,在现实世界中有2000多个条目和更多的数据

2 个答案:

答案 0 :(得分:1)

你最大的问题是过滤。对于每个列表的每个元素,您将搜索整个其他列表以查看它是否存在。这需要二次时间。如果将这些对象转换为名称组或由名称键控的dicts,则可以消除该二次函数并使其成为对数线性。

之后,sorted也不再需要了,这是代码是对数线性的唯一原因,所以现在它是线性的。

当我们处于它的时候,你正在浪费内存,可能是时间,建立一个列表只是为了在下一行的生成器表达式中迭代它。如果我们摆脱sorted,这就变得更加重要,因为那时我们永远不需要列表。

所以:

dict_a = {x._name: x for x in list_a}
for d in list_b:
    try:
        dict_a[d['name']].update(d)
    except KeyError:
        pass

使用try / except进行dict查找会在没有匹配对象的情况下过滤掉dicts,并且您不需要在没有匹配dicts的情况下过滤掉对象,因为它们不会被调用。

如果有更多的词组而不是对象,则反转词来制作词典的词典并迭代对象。

或者,如果您可以首先将对象保存在dict中,而不是将它们保留在列表中并为此代码创建临时dict,那就更好了。如果您在解析时逐个迭代dicts然后关闭服务器响应而不是首先构建它们的列表,那么您将消除所有不必要的大量分配,并可能进一步加快速度。

答案 1 :(得分:0)

不应将对象存储在列表中,而应将该列表转换为dict:

objects_by_name = {obj._name: obj for obj in list_a}

这使您可以在O(1)时间内查找与名称关联的对象。

现在,更新所有对象就像迭代list_b一样简单,从dict中获取相应的对象,并调用其update方法:

for dic in list_b:
    obj = objects_by_name[dic['name']]
    obj.update(dic)

总体而言,时间复杂度为O(n),而您的代码为O(n log n),因为排序。