如何从字典中获取值列表?

622

如何在Python中获取字典中的值列表?

在Java中,将Map的值作为List获取只需执行list = map.values();即可。 我想知道是否有类似简单的方法可以从Python字典中获取值列表。

7个回答

974

1
在Python 3中,iter(d.values())返回字典值的迭代器,它不会立即消耗内存。 - Peterino
2
@Peterino 是的,虽然在Python 3中你很少需要显式调用iter(d.values())。你可以直接迭代这些值:for value in d.values(): 顺便说一下,在大多数实际使用情况下,这也是每个人都会做的事情。通常你不需要一个字典值列表,只是为了像这个问题一样拥有一个列表。我所做的许多这些Python 2评论现在几乎没有用处,可能会让现在阅读此内容的Python 3程序员感到困惑。 - jamylak
@jamylak:拿这个用例来说,一个API想要返回字典的值。在这里,你不会进行迭代(除非你使用列表或生成器推导式),而是应用list()iter(),根据你的喜好和进一步的处理方式。 - Peterino
@Peterino 好的,没问题。 - jamylak

98
您可以使用 * 运算符 来解包 dict_values:
>>> d = {1: "a", 2: "b"}
>>> [*d.values()]
['a', 'b']

或者列表对象

>>> d = {1: "a", 2: "b"}
>>> list(d.values())
['a', 'b']

8
哪一个更快? - BigChief
@BigChief 这里发布了一些时间 https://dev59.com/VWQo5IYBdhLWcg3wOdJZ#56736691 我还没有验证它们,但也许这可以回答你的问题。我认为真正重要的是清晰度而不是原始速度。 - jamylak
啊,非常有趣。总的来说,研究发现对于较小的集合来说,解包速度更快,而对于较大的集合来说,转换为列表更快。 - BigChief

68

应该有一种 ‒ 最好只有一种 ‒ 显而易见的方法来做。

因此,list(dictionary.values())就是这个唯一的方法

然而,考虑Python3,哪种方法更快?

[*L] vs. [].extend(L) vs. list(L)

small_ds = {x: str(x+42) for x in range(10)}
small_df = {x: float(x+42) for x in range(10)}

print('Small Dict(str)')
%timeit [*small_ds.values()]
%timeit [].extend(small_ds.values())
%timeit list(small_ds.values())

print('Small Dict(float)')
%timeit [*small_df.values()]
%timeit [].extend(small_df.values())
%timeit list(small_df.values())

big_ds = {x: str(x+42) for x in range(1000000)}
big_df = {x: float(x+42) for x in range(1000000)}

print('Big Dict(str)')
%timeit [*big_ds.values()]
%timeit [].extend(big_ds.values())
%timeit list(big_ds.values())

print('Big Dict(float)')
%timeit [*big_df.values()]
%timeit [].extend(big_df.values())
%timeit list(big_df.values())
Small Dict(str)
256 ns ± 3.37 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
338 ns ± 0.807 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
336 ns ± 1.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Small Dict(float)
268 ns ± 0.297 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
343 ns ± 15.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
336 ns ± 0.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Big Dict(str)
17.5 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
16.5 ms ± 338 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
16.2 ms ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Big Dict(float)
13.2 ms ± 41 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
13.1 ms ± 919 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
12.8 ms ± 578 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

在 Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz 上完成。

# Name                    Version                   Build
ipython                   7.5.0            py37h24bf2e0_0

结果

  1. 对于小字典,使用*运算符更快。
  2. 对于大字典,在需要时使用list()可能略快。

4
感谢分享基准测试结果。只是有一个小更新:在使用Python 3.10和大字典的情况下,在Apple Silicon上已经没有区别了。 - Michael Dorner

20

请按照以下示例操作 --

songs = [
{"title": "happy birthday", "playcount": 4},
{"title": "AC/DC", "playcount": 2},
{"title": "Billie Jean", "playcount": 6},
{"title": "Human Touch", "playcount": 3}
]

print("====================")
print(f'Songs --> {songs} \n')
title = list(map(lambda x : x['title'], songs))
print(f'Print Title --> {title}')

playcount = list(map(lambda x : x['playcount'], songs))
print(f'Print Playcount --> {playcount}')
print (f'Print Sorted playcount --> {sorted(playcount)}')

# Aliter -
print(sorted(list(map(lambda x: x['playcount'],songs))))

2
如果您需要将值作为列表分配给变量,可以使用另一种使用解包 * 运算符的方法:
*values, = d.values()
获取字典中特定键的值列表

最简单的方法是使用推导式,通过迭代 list_of_keys 来实现。如果 list_of_keys 包含不是 d 的键,则可以使用 .get() 方法返回一个默认值(默认为 None,但可以更改)。

res = [d[k] for k in list_of_keys] 
# or
res = [d.get(k) for k in list_of_keys]

通常情况下,Python内置了一种方法可以获取键下的值:operator模块中的itemgetter()

from operator import itemgetter
res = list(itemgetter(*list_of_keys)(d))

演示:

d = {'a':2, 'b':4, 'c':7}
list_of_keys = ['a','c']
print([d.get(k) for k in list_of_keys])
print(list(itemgetter(*list_of_keys)(d)))
# [2, 7]
# [2, 7]
从字典列表中获取相同键的值

这里可以使用列表推导式来遍历字典列表,也可以使用itemgetter()函数映射到列表中以获取特定键的值。

list_of_dicts = [ {"title": "A", "body": "AA"}, {"title": "B", "body": "BB"} ]

list_comp = [d['title'] for d in list_of_dicts]
itmgetter = list(map(itemgetter('title'), list_of_dicts))
print(list_comp)
print(itmgetter)
# ['A', 'B']
# ['A', 'B']

0
如果你想要默认返回一个列表(就像Python 2中那样)而不是视图,可以创建一个新的字典类并覆盖values方法:
class ldict(dict):
    # return a simple list instead of dict_values object
    values = lambda _: [*super().values()]

d = ldict({'a': 1, 'b': 2})
d.values()   # [1, 2]   (instead of dict_values([1, 2]))

-4
out: dict_values([{1:a, 2:b}])

in:  str(dict.values())[14:-3]    
out: 1:a, 2:b

仅用于视觉目的。不产生有用的产品……仅在您想要将长字典打印成段落形式时有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接