【问题标题】:label assignment from lookup dictionary keys and value in PythonPython中查找字典键和值的标签分配
【发布时间】:2021-11-20 16:31:36
【问题描述】:

给定一个列表

[0,1,2,3,4,5,6,7,8,9,10,11,12,13]

我想在每个列表位置标记如下

['fir', 'fir', 'sec', 'fir', 'fir', 'fir', 'thr', 'sec', 'fou', 'fou', 'fou', 'thr', 'sec', 'fou']

关于查找字典m

m={ "fir": [0,1,3,4,5],
        "sec": [2,7,12],
        "thr": [6,11],
        "fou": [8,9,10,13]}

以前三个位置为例。

从字典m,位置01 属于键fir。而第三个位置(例如 2)在键 sec 下。

因此,这三个的列表是 ['fir', 'fir', 'sec']。

为实现上述目标,特拟如下

m={ "fir": [0,1,3,4,5],
        "sec": [2,7,12],
        "thr": [6,11],
        "fou": [8,9,10,13]}

all_key=m.keys()
all_opt=[]
for idx in range (sum(len(v) for v in m.values())):
  for nkey in all_key:
    if idx in m[nkey]:
      all_opt.append(nkey)
      break

  

生产的

opt=['fir', 'fir', 'sec', 'fir', 'fir', 'fir', 'thr', 'sec', 'fou', 'fou', 'fou', 'thr', 'sec', 'fou']

我想知道是否有比嵌套 for 循环更好的替代方案?

【问题讨论】:

  • 整体上反转m 以将索引号映射到单词,然后使用它可能会更有效。

标签: python performance dictionary


【解决方案1】:

您可以反转映射字典,以便映射为:

  • value<sub>i</sub> ⟶ label<sub>j</sub> 而不是 label ⟶ [value<sub>0</sub>...value<sub>n</sub>]

您可以使用字典理解来反转字典

inv_m = {v: k for k, lst in m.items() for v in lst}
print(inv_m)
# {0: 'fir', 1: 'fir', 3: 'fir', 4: 'fir', 5: 'fir', 2: 'sec',
#  7: 'sec', 12: 'sec', 6: 'thr', 11: 'thr', 8: 'fou', 9: 'fou',
#  10: 'fou', 13: 'fou'}

现在,遍历给定的列表并将每个值映射到其对应的标签。

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
out = [inv_m[v] for v in lst]
print(out)
# ['fir', 'fir', 'sec', 'fir', 'fir', 'fir', 'thr', 'sec', 'fou',
#  'fou', 'fou', 'thr', 'sec', 'fou']

【讨论】:

  • 对于该数据,它花费的时间大约是 OP 的一半,但是其他答案的两倍。
  • @KellyBundy 是的,我 timeit 的结果与您在更大数据(10,000 个元素)上的结果类似。我的错我认为列表中的值可能不是索引。例如,lst = ['a', 'b', 'c']; m = {"fir": ["a", "b"], "sec": ["c"]}
  • @KellyBundy 但是如果这被称为 1000 次,我们只需要构建一次 inv_m,其余 999 次列表就足够了,除非添加新标签。将out = [inv_m[v] ...] 更改为list(map(inv_m.get, lst)) 后,速度要快得多。对于第一次运行,我的解决方案包括构建 inv_mlist(map(...)) 几乎比其他答案慢 2 倍。休息 999 次,我不需要构建 inv_m,所以我根据他的代码对我的 list(map(...)) 计时。 list(map(...)) 更快,但平均差异仅为 60 µs 左右。
  • 我认为仅将您的流程的一部分与他们的整个流程进行比较是没有意义的。为什么只需要构建一次inv_m?只要m 更改,inv_m 也必须更改。
  • @KellyBundy 那是我在我的 cmets 中提到的。如果m 没有,你为什么要每次都构建它?如果m 不断变化,那么我们每次都会构建它。
【解决方案2】:

创建一个固定大小的列表并通过将标签添加到相应的索引来填充它:

lst = [0,1,2,3,4,5,6,7,8,9,10,11,12,13]
m = { 
    "fir": [0,1,3,4,5],
    "sec": [2,7,12],
    "thr": [6,11],
    "fou": [8,9,10,13]
}

label_lst = [''] * len(lst)
for label, idxs in m.items():
    for idx in idxs:    
        label_lst[idx] = label

print(label_lst)

输出

['fir', 'fir', 'sec', 'fir', 'fir', 'fir', 'thr', 'sec', 'fou', 'fou', 'fou', 'thr', 'sec', 'fou']

【讨论】:

  • 这是直截了当的答案,应该是最重要的。基准测试可能很好(特别是因为问题标记为performance)。
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-14
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
相关资源
最近更新 更多