如何在(k,v)对使用列表中的连续项的Python中迭代字典

时间:2019-03-04 06:34:42

标签: python loops dictionary range key

我想将(k,v)对添加到字典weights中,其中该字典的键等于列表layers中的对象。该值的构造使得它使用此列表中的对象l和对象l+1。我目前这样做如下:

layers = self.layers

for l in range(0, layers.__len__() - 1):
   weights[layers[l]] = np.random.rand(
      layers[l + 1].node_cardinality, 
      layers[l].node_cardinality + 1 
   )

是否有一种更好,更短的方法而不必使用range()代码?

2 个答案:

答案 0 :(得分:2)

以第二个项目开头的层和层的切片作为邮政编码。请注意,zip()将在其所有可迭代项用尽后立即停止。

for L0, L1 in zip(layers, layers[1:]):
   weights[L0] = np.random.rand(
       L1.node_cardinality, 
       L0.node_cardinality + 1 
   )

根据序列layers的类型,使用itertools.islice代替普通切片可能会更有效。如果进行切片,则numpy数组可能只会使用视图。但是列表必须创建一个(浅)副本,因此,如果长度很长,则islice更好。

for L0, L1 in zip(layers, islice(layers, 1, None)):
   weights[L0] = np.random.rand(
       L1.node_cardinality, 
       L0.node_cardinality + 1 
   )

正如GrazingScientist指出的那样,也可以通过字典理解来完成。

weights.update(
    {
        L0: np.random.rand(L1.node_cardinality, L0.node_cardinality + 1)
        for L0, L1 in zip(layers, layers[1:])
    }
)

但是这种方法必须在更新之前生成一个新的字典,这可能会占用更多的内存。如果layers长,则for循环可能会更好。但是字典仅包含引用,因此它可能并不比使用普通列表切片差很多。

在这种情况下,使用生成器表达式实际上会更有效。 .update()方法还可以接受(k, v)对的可迭代对象,但是生成器不必一次分配它们。一次只做一对。

weights.update(
    (L0, np.random.rand(L1.node_cardinality, L0.node_cardinality + 1))
    for L0, L1 in zip(layers, islice(layers, 1, None))
)

答案 1 :(得分:0)

我建议使用enumeratedict comprehension。这是更pythonic的,可能更快。

layers = self.layers
buf_dict = {layers[i]: np.random.rand(layers[i + 1].node_cardinality, layers[i].node_cardinality + 1)
for i, l in zip(layers, layers[1:])}
weights.update(buf_dict)

编辑:忘记了代码,并确认zip在这种情况下实际上比枚举更好(这要感谢gilch),因为您不会遇到IndexError。