通过从另一个列表执行查找来替换元组列表中的元素的有效方法(python)

通过从另一个列表执行查找来替换元组列表中的元素的有效方法(python),python,Python,我有一个元组列表,如下所示: tuple_list = [(id-1,value-1),(id-2,value-2),....(id-n,value-n)] 同样,我有一个与上面列表中的id相关的对象列表,即: object_list = [<obj-3>,<obj-1>,....<obj-n>] 执行此操作的最有效方式是什么 我目前正在两个for循环中尝试: resulting_list = [] for tpl in tuple_list:

我有一个元组列表,如下所示:

tuple_list = [(id-1,value-1),(id-2,value-2),....(id-n,value-n)]
同样,我有一个与上面列表中的
id
相关的对象列表,即:

object_list = [<obj-3>,<obj-1>,....<obj-n>]
执行此操作的最有效方式是什么


我目前正在两个for循环中尝试:

resulting_list = []
for tpl in tuple_list:
    for obj in object_list:
        if tpl[0] == obj.id
        resulting_list.append((obj,tpl[1]))

构造一个
dict
,其中键是对象ID,值是对象。然后在列表理解中迭代
tuple\u list
,对于
dict
中的每个tuple输出对象和原始列表中的值:

class Obj:
    def __init__(self, id):
        self.id = id

    def __repr__(self):
        return 'Obj({})'.format(self.id)

tuple_list = [(0, 'Zero'), (1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four')]
object_list = [Obj(i) for i in range(4, -1, -1)]

d = {o.id: o for o in object_list}
result = [(d[_id], val) for _id, val in tuple_list]

print(result)
输出:

[(Obj(0), 'Zero'), (Obj(1), 'One'), (Obj(2), 'Two'), (Obj(3), 'Three'), (Obj(4), 'Four')]

上面的时间复杂度是O(n),其中带有嵌套循环的原始代码是O(n^2)

构造一个
dict
,其中键是对象ID,值是对象。然后在列表理解中迭代
tuple\u list
,对于
dict
中的每个tuple输出对象和原始列表中的值:

class Obj:
    def __init__(self, id):
        self.id = id

    def __repr__(self):
        return 'Obj({})'.format(self.id)

tuple_list = [(0, 'Zero'), (1, 'One'), (2, 'Two'), (3, 'Three'), (4, 'Four')]
object_list = [Obj(i) for i in range(4, -1, -1)]

d = {o.id: o for o in object_list}
result = [(d[_id], val) for _id, val in tuple_list]

print(result)
输出:

[(Obj(0), 'Zero'), (Obj(1), 'One'), (Obj(2), 'Two'), (Obj(3), 'Three'), (Obj(4), 'Four')]

上面的时间复杂度是O(n),其中带有嵌套循环的原始代码是O(n^2)

如果列表的长度是
n
,那么当前算法在外循环上进行
n
迭代,在每个内循环上进行
n
迭代,总共给出
n*n
。您可以通过在找到匹配项后立即打破内部循环来改进这一点。这将给出
n*n/2
的平均值

但是最好做两个循环,每个循环长度
n
,因为对于大型
n
2n
n*n
小得多。在下面的代码中,第一个循环构造一个字典,对象id作为键,对象本身作为值。然后,第二个循环可以从其id快速找到对象

obj_map = {obj.id: obj for obj in object_list}
resulting_list = [(obj_map[k], v) for k, v in tuple_list]

如果
tuple\u list
中的某些ID在
obj\u map
中可能没有匹配的对象,并且您不希望在这种情况下出现
keyrorm
失败,那么您可以这样做

resulting_list = [(obj_map.get(k), v) for k, v in tuple_list]
它将为任何缺少的对象提供
None

...
    i = object_list.index(tpl[0]) if tpl[0] in tuple_list else -1
    if i > -1:
      resulting_list.append((object_list[i],tpl[1]))
或者

resulting_list = [(obj_map.get(k, default_object), v) for k, v in tuple_list]

它将为缺少的对象提供默认对象。

如果列表的长度为
n
,则当前算法在外循环上进行
n
迭代,在每个内循环上进行
n
迭代,总共给出
n*n
。您可以通过在找到匹配项后立即打破内部循环来改进这一点。这将给出
n*n/2
的平均值

...
    i = object_list.index(tpl[0]) if tpl[0] in tuple_list else -1
    if i > -1:
      resulting_list.append((object_list[i],tpl[1]))
但是最好做两个循环,每个循环长度
n
,因为对于大型
n
2n
n*n
小得多。在下面的代码中,第一个循环构造一个字典,对象id作为键,对象本身作为值。然后,第二个循环可以从其id快速找到对象

obj_map = {obj.id: obj for obj in object_list}
resulting_list = [(obj_map[k], v) for k, v in tuple_list]

如果
tuple\u list
中的某些ID在
obj\u map
中可能没有匹配的对象,并且您不希望在这种情况下出现
keyrorm
失败,那么您可以这样做

resulting_list = [(obj_map.get(k), v) for k, v in tuple_list]
它将为任何缺少的对象提供
None

...
    i = object_list.index(tpl[0]) if tpl[0] in tuple_list else -1
    if i > -1:
      resulting_list.append((object_list[i],tpl[1]))
或者

resulting_list = [(obj_map.get(k, default_object), v) for k, v in tuple_list]

它将为缺少的对象提供
默认对象

是否保证
元组列表
中的每个id在
对象列表
?@PM2Ring:yes,保证
元组列表
中的每个id在
对象列表
?@PM2Ring:yes,guaranteed@MarcusM是的,是的。但是这里没有给我们一个(键,值)元组的iterable。它不是
(hashable,value)
?@MarcusMüller是的,它是。但是这里没有给我们一个(键,值)元组的iterable,不是吗?
...
    i = object_list.index(tpl[0]) if tpl[0] in tuple_list else -1
    if i > -1:
      resulting_list.append((object_list[i],tpl[1]))