简体   繁体   English

python比较列表值和字典列表中的键

[英]python comparing list values to keys in list of dicts

I have a list of dicts a and a list b as shown below. 我有一个字典a列表和一个列表b,如下所示。 len(b) will not always be 4. it may be 2 or 3. I compared values in b to keys in each dict in b. len(b)并不总是4。它可能是2或3。我将b中的值与b中每个字典的键进行了比较。 I obtained the result shown, which should rightly be of length b but the order is not as desired. 我获得了所示的结果,该结果正确地应为长度b,但顺序不理想。

My 2 problems are: 我的两个问题是:

  1. The result is not printed in order. 结果未按顺序打印。 ie not depending on which value comes first in my list 即不取决于哪个值是我列表中的第一位
  2. Is there a better way of comparison? 有更好的比较方法吗? ( I am sure there is) because len(b) will not always be 4. It may be smaller. (我肯定有),因为len(b)并不总是4。它可能会更小。

Here is what I have 这是我所拥有的

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)

My result is 我的结果是

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

If you notice, for b = 2 ie b[0] , the result from a[1 ] is rightly 7 but it comes after 0 and 1 in my final result even though 2 is the first item in b. 如果您注意到,对于b = 2b[0] ,来自a[1 ]的结果恰好是7,但即使2是b中的第一项,它的最终结果还是在0和1之后。

Thank you 谢谢

You can use a list comprehension: 您可以使用列表理解:

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]]

To understand how this works, it sometimes helps to write out the full nested for loop: 要了解其工作原理,有时有助于写出完整的嵌套for循环:

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

A functional approach is also possible: 功能方法也是可行的:

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

The problem is, you do not iterate with regards to b . 问题是,您没有对b进行迭代。 You iterate with regards to key order in dictionaries inside a . 您可以根据内字典对键顺序进行迭代。 Thats why output elements are out of order. 这就是为什么输出元素乱序。

For the correct solution, you should iterate with regards to b's items, like this: 为了获得正确的解决方案,您应该对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)

Prints: 印刷品:

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]]

You could also use operator.itemgetter which provides a neat shorthand to retrieve multiple items in one go: 您还可以使用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)

Now for example: 现在举个例子:

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

The result is a tuple, not a list. 结果是一个元组,而不是列表。 If that's ok you can make a list comprehension or use map: 如果可以,您可以进行列表理解或使用map:

>>> [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)]

If it must be lists, it's a bit more cumbersome: 如果必须是列表,那么会比较麻烦:

>>> [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]]

On my system itemgetter appears to be a bit faster than one-by-one lookup even if we have to convert tuples to lists: 在我的系统上,即使我们必须将元组转换为列表, 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM