获取键列表的值列表

2025-01-15 08:46:00
admin
原创
25
摘要:问题描述:是否有内置/快速的方法使用字典中的键列表来获取相应项目的列表?例如我有:>>> mydict = {'one': 1, 'two': 2, 'three': 3} >>> mykeys = ['three', 'one'] 如何使用mykeys列表获取字典中的相应...

问题描述:

是否有内置/快速的方法使用字典中的键列表来获取相应项目的列表?

例如我有:

>>> mydict = {'one': 1, 'two': 2, 'three': 3}
>>> mykeys = ['three', 'one']

如何使用mykeys列表获取字典中的相应值?

>>> mydict.WHAT_GOES_HERE(mykeys)
[3, 1]

解决方案 1:

列表推导式似乎是实现此目的的好方法:

>>> [mydict[x] for x in mykeys]
[3, 1]

解决方案 2:

除了列表计算之外,还有其他几种方法:

  • 建立列表,如果找不到键则抛出异常:map(mydict.__getitem__, mykeys)

  • None如果未找到键,则构建列表:map(mydict.get, mykeys)

或者,使用operator.itemgetter可以返回一个元组:

from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required

注意:在 Python3 中,map返回的是迭代器而不是列表。用于list(map(...))列表。

解决方案 3:

一点速度比较:

Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec  7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[1]: l = [0,1,2,3,2,3,1,2,0]
In[2]: m = {0:10, 1:11, 2:12, 3:13}
In[3]: %timeit [m[_] for _ in l]  # list comprehension
1000000 loops, best of 3: 762 ns per loop
In[4]: %timeit map(lambda _: m[_], l)  # using 'map'
1000000 loops, best of 3: 1.66 µs per loop
In[5]: %timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
1000000 loops, best of 3: 1.65 µs per loop
In[6]: %timeit map(m.__getitem__, l)
The slowest run took 4.01 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 853 ns per loop
In[7]: %timeit map(m.get, l)
1000000 loops, best of 3: 908 ns per loop
In[33]: from operator import itemgetter
In[34]: %timeit list(itemgetter(*l)(m))
The slowest run took 9.26 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 739 ns per loop

因此,列表理解和 itemgetter 是实现此目的的最快方法。

更新

对于大型随机列表和地图,我得到了一些不同的结果:

Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Dec  7 2015, 14:10:42) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)

%timeit f(m)
1000 loops, best of 3: 1.14 ms per loop

%timeit list(itemgetter(*l)(m))
1000 loops, best of 3: 1.68 ms per loop

%timeit [m[_] for _ in l]  # list comprehension
100 loops, best of 3: 2 ms per loop

%timeit map(m.__getitem__, l)
100 loops, best of 3: 2.05 ms per loop

%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
100 loops, best of 3: 2.19 ms per loop

%timeit map(m.get, l)
100 loops, best of 3: 2.53 ms per loop

%timeit map(lambda _: m[_], l)
100 loops, best of 3: 2.9 ms per loop

因此,在这种情况下,明显的赢家是f = operator.itemgetter(*l); f(m),而明显的局外人是:map(lambda _: m[_], l)

针对 Python 3.6.4 的更新

import numpy.random as nprnd
l = nprnd.randint(1000, size=10000)
m = dict([(_, nprnd.rand()) for _ in range(1000)])
from operator import itemgetter
import operator
f = operator.itemgetter(*l)

%timeit f(m)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit list(itemgetter(*l)(m))
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit [m[_] for _ in l]  # list comprehension
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(map(m.__getitem__, l))
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(map(m.get, l))
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit list(map(lambda _: m[_], l)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

因此,Python 3.6.4 的结果几乎相同。

解决方案 4:

这里有三种方法。

KeyError当找不到密钥时引发:

result = [mapping[k] for k in iterable]

缺少键的默认值。

result = [mapping.get(k, default_value) for k in iterable]

跳过丢失的钥匙。

result = [mapping[k] for k in iterable if k in mapping]

解决方案 5:

尝试一下:

mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one','ten']
newList=[mydict[k] for k in mykeys if k in mydict]
print newList
[3, 1]

解决方案 6:

尝试一下:

mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one'] # if there are many keys, use a set

[mydict[k] for k in mykeys]
=> [3, 1]

解决方案 7:

new_dict = {x: v for x, v in mydict.items() if x in mykeys}

解决方案 8:

Pandas 做得非常优雅,尽管列表推导在技术上总是更符合 Python 风格。我现在没时间做速度比较(我稍后会回来做):

import pandas as pd
mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one']
temp_df = pd.DataFrame().append(mydict)
# You can export DataFrames to a number of formats, using a list here. 
temp_df[mykeys].values[0]
# Returns: array([ 3.,  1.])

# If you want a dict then use this instead:
# temp_df[mykeys].to_dict(orient='records')[0]
# Returns: {'one': 1.0, 'three': 3.0}

解决方案 9:

如果您想在尝试访问键之前确保键存在于字典中,则可以使用集合类型。将字典键和您请求的键转换为集合。然后使用该issubset()方法。

mydict = {'one': 1, 'two': 2, 'three': 3}
mykeys = ['three', 'one']
assert set(mykeys).issubset(set(mydict.keys()))
result = [mydict[key] for key in mykeys]

解决方案 10:

一些新的答案。

(1)如果你的类似字典的对象需要构造,我发现这样做很有用,这样只需构造一次:

train_data, train_labels, test_data, test_labels = [
    d[k] for d in [numpy.load('classify.npz')]
    for k in 'train_data train_labels test_data test_labels'.split()]

(2) python 3.10 具有 dict 模式匹配,它允许以下类型的模式。

match numpy.load('classify.npz'):
    case {
        'train_data': train_data,
        'train_labels': train_labels,
        'test_data': test_data,
        'test_labels': test_labels}: pass
    case _: raise KeyError()

解决方案 11:

Python闭包 :根据给定顺序从字典值创建列表的有效方法

检索密钥但不建立列表:

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)

import collections


class DictListProxy(collections.Sequence):
    def __init__(self, klist, kdict, *args, **kwargs):
        super(DictListProxy, self).__init__(*args, **kwargs)
        self.klist = klist
        self.kdict = kdict

    def __len__(self):
        return len(self.klist)

    def __getitem__(self, key):
        return self.kdict[self.klist[key]]


myDict = {'age': 'value1', 'size': 'value2', 'weigth': 'value3'}
order_list = ['age', 'weigth', 'size']

dlp = DictListProxy(order_list, myDict)

print(','.join(dlp))
print()
print(dlp[1])

输出:

value1,value3,value2

value3

与列表给出的顺序相匹配

解决方案 12:

如果您发现自己经常这样做,您可能需要子类化dict以获取键列表并返回值列表。

>>> d = MyDict(mydict)
>>> d[mykeys]
[3, 1]

这是一个演示实现。

class MyDict(dict):
    def __getitem__(self, key):
        getitem = super().__getitem__
        if isinstance(key, list):
            return [getitem(x) for x in key]
        else:
            return getitem(key)

很好地进行子类化dict需要做更多的工作,另外您可能还想要实现.get().__setitem__().__delitem__()等等。

解决方案 13:

reduce(lambda x,y: mydict.get(y) and x.append(mydict[y]) or x, mykeys,[])

以防万一有字典中没有的键。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1041  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   34  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   31  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   23  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   26  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用