python将列表值与dicts列表中的键进行比较

时间:2018-05-20 19:49:23

标签: python

我有一个词典a和列表b的列表,如下所示。 len(b)并不总是4.它可能是2或3.我将b中的值与b中每个dict中的键进行比较。我得到了显示的结果,它应该正好是长度为b但是顺序不是所希望的。

我的两个问题是:

  1. 结果未按顺序打印。即不依赖于我的清单中的第一个值
  2. 有更好的比较方式吗? (我确信有)因为len(b)并不总是4.它可能更小。
  3. 这就是我所拥有的

    a = [{0: 0, 1: 1, 2: 7, 3: 0}, {0: 0, 1: 0, 2: 12, 3: 0}, {0: 5, 1: 0, 2: 8, 3: 0}]
    b = [2, 0, 1, 3]
    c = []
    for i in a:
        x = []
        for k, v in i.items():
            if k == b[0]: 
               x.append(v)
            if k == b[1]:
                x.append(v)
            if k == b[2]:
                x.append(v)
            if k == b[3]:
                x.append(v)
        c.append(x)
    print(c)
    

    我的结果是

    [[0, 1, 7, 0], [0, 0, 12, 0], [5, 0, 8, 0]]

    如果您注意到,对于b = 2b[0],来自a[1的结果正确为7,但是在我的最终结果中为0和1之后,即使2是第一项在b。

    谢谢

3 个答案:

答案 0 :(得分:1)

您可以使用列表理解:

res = [[d[i] for i in b] for d in a]

print(res)

[[7, 0, 1, 0], [12, 0, 0, 0], [8, 5, 0, 0]]

要了解其工作原理,有时会写出完整的嵌套for循环:

res = []
for d in a:
    res_int = []
    for i in b:
        res_int.append(d[i])
    res.append(res_int)

也可以采用功能性方法:

res = [list(map(d.get, b)) for d in a]

答案 1 :(得分:1)

问题是,您不会针对b 重复。您可以在 a 中的字典中重复关键顺序。这就是输出元素出现故障的原因。

对于正确的解决方案,您应该对b的项目进行迭代,如下所示:

a = [{0: 0, 1: 1, 2: 7, 3: 0}, {0: 0, 1: 0, 2: 12, 3: 0}, {0: 5, 1: 0, 2: 8, 3: 0}]
b = [2, 0, 1, 3]
c = []
for a_dict in a:
    x = []
    for b_element in b:
        if b_element in a_dict:
            x.append(a_dict[b_element])
            print("Appending %ss value %s to X! new X: %s" % (b_element, a_dict[b_element], str(x)))
    c.append(x)
print(c)

打印:

Appending Key:2s Value:7 to X! new X: [7]
Appending Key:0s Value:0 to X! new X: [7, 0]
Appending Key:1s Value:1 to X! new X: [7, 0, 1]
Appending Key:3s Value:0 to X! new X: [7, 0, 1, 0]
Appending Key:2s Value:12 to X! new X: [12]
Appending Key:0s Value:0 to X! new X: [12, 0]
Appending Key:1s Value:0 to X! new X: [12, 0, 0]
Appending Key:3s Value:0 to X! new X: [12, 0, 0, 0]
Appending Key:2s Value:8 to X! new X: [8]
Appending Key:0s Value:5 to X! new X: [8, 5]
Appending Key:1s Value:0 to X! new X: [8, 5, 0]
Appending Key:3s Value:0 to X! new X: [8, 5, 0, 0]
[[7, 0, 1, 0], [12, 0, 0, 0], [8, 5, 0, 0]]

答案 2 :(得分:1)

你也可以使用operator.itemgetter提供一个简洁的速记来一次检索多个项目:

>>> a = [{0: 0, 1: 1, 2: 7, 3: 0}, {0: 0, 1: 0, 2: 12, 3: 0}, {0: 5, 1: 0, 2: 8, 3: 0}]
>>> b = [2, 0, 1, 3]
>>> 
>>> from operator import itemgetter
>>> get_b = itemgetter(*b)

现在举例:

>>> get_b(a[0])
(7, 0, 1, 0)

结果是一个元组,而不是一个列表。如果没关系,你可以制作列表理解或使用地图:

>>> [get_b(d) for d in a]
[(7, 0, 1, 0), (12, 0, 0, 0), (8, 5, 0, 0)]
>>> list(map(get_b, a))
[(7, 0, 1, 0), (12, 0, 0, 0), (8, 5, 0, 0)]

如果它必须是列表,那就更麻烦了:

>>> [list(get_b(d)) for d in a]
[[7, 0, 1, 0], [12, 0, 0, 0], [8, 5, 0, 0]]
>>> list(map(list, map(get_b, a)))
[[7, 0, 1, 0], [12, 0, 0, 0], [8, 5, 0, 0]]

在我的系统上itemgetter似乎比逐个查找快一点,即使我们必须将元组转换为列表:

>>> from timeit import timeit
>>>
>>> def multi_get(a, b):
...     get_b = itemgetter(*b)
...     return [[*get_b(d),] for d in a]
... 
>>> def multi_get_tuple(a, b):
...     get_b = itemgetter(*b)
...     return [get_b(d) for d in a]
... 
>>> timeit("multi_get_tuple(a, b)", globals=globals(), number=1000000)
0.9130640690000291
>>> timeit("multi_get(a, b)", globals=globals(), number=1000000)
1.0864301430010528
>>> timeit("[[d[i] for i in b] for d in a]", globals=globals(), number=1000000)
1.40757593699891