簡體   English   中英

python比較列表值和字典列表中的鍵

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

我有一個字典a列表和一個列表b,如下所示。 len(b)並不總是4。它可能是2或3。我將b中的值與b中每個字典的鍵進行了比較。 我獲得了所示的結果,該結果正確地應為長度b,但順序不理想。

我的兩個問題是:

  1. 結果未按順序打印。 即不取決於哪個值是我列表中的第一位
  2. 有更好的比較方法嗎? (我肯定有),因為len(b)並不總是4。它可能會更小。

這是我所擁有的

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,但即使2是b中的第一項,它的最終結果還是在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]

問題是,您沒有對b進行迭代。 您可以根據內字典對鍵順序進行迭代。 這就是為什么輸出元素亂序。

為了獲得正確的解決方案,您應該對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]]

您還可以使用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)

結果是一個元組,而不是列表。 如果可以,您可以進行列表理解或使用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)]

如果必須是列表,那么會比較麻煩:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM