Python字典:获取键列表的值列表

Python字典:获取键列表的值列表,python,list,dictionary,key,Python,List,Dictionary,Key,是否有一种内置/快速的方法可以使用字典的键列表来获取相应项的列表 例如,我有: >>> mydict = {'one': 1, 'two': 2, 'three': 3} >>> mykeys = ['three', 'one'] 如何使用mykeys获取字典中的对应值作为列表 >>> mydict.WHAT_GOES_HERE(mykeys) [3, 1] 列表理解似乎是一种很好的方法: >>> [mydict[x]

是否有一种内置/快速的方法可以使用字典的键列表来获取相应项的列表

例如,我有:

>>> mydict = {'one': 1, 'two': 2, 'three': 3}
>>> mykeys = ['three', 'one']
如何使用
mykeys
获取字典中的对应值作为列表

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

列表理解似乎是一种很好的方法:

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

列表理解似乎是一种很好的方法:

>>> [mydict[x] for x in mykeys]
[3, 1]
或者只是
mydict.keys()
这是字典的内置方法调用。同时探索
mydict.values()
mydict.items()

//啊,这篇文章把我弄糊涂了

或只是
mydict.keys()
这是字典的内置方法调用。同时探索
mydict.values()
mydict.items()

//啊,这篇文章把我弄糊涂了

试试这个:

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]
试试这个:

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]

除列表比较外,还有其他几种方法:

  • 如果找不到键,则生成列表并引发异常:
    map(mydict.\uu getitem\uuuu,mykeys)
  • 如果未找到键,则使用
    None
    生成列表:
    map(mydict.get,mykeys)
或者,使用
操作符.itemgetter
可以返回元组:

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

注意:在Python3中,
map
返回迭代器而不是列表。使用
列表(映射(…)
获取列表。

除了列表比较外,还有其他几种方法:

reduce(lambda x,y: mydict.get(y) and x.append(mydict[y]) or x, mykeys,[])
  • 如果找不到键,则生成列表并引发异常:
    map(mydict.\uu getitem\uuuu,mykeys)
  • 如果未找到键,则使用
    None
    生成列表:
    map(mydict.get,mykeys)
或者,使用
操作符.itemgetter
可以返回元组:

from operator import itemgetter
myvalues = itemgetter(*mykeys)(mydict)
# use `list(...)` if list is required
注意:在Python3中,
map
返回迭代器而不是列表。使用
列表(映射(…)
获取列表

reduce(lambda x,y: mydict.get(y) and x.append(mydict[y]) or x, mykeys,[])
万一字典里没有钥匙

如果有不在目录中的键。

这里有三种方法

找不到钥匙时引发钥匙错误:

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]
跳过丢失的键

result = [mapping.get(k, default_value) for k in iterable]
result = [mapping[k] for k in iterable if k in mapping]
这里有三种方法

找不到钥匙时引发钥匙错误:

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]
跳过丢失的键

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

一点速度比较:

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)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l]  # list comprehension
%timeit map(m.__getitem__, l)
%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
%timeit map(m.get, l)
%timeit map(lambda _: m[_], l)
1000 loops, best of 3: 1.14 ms per loop
1000 loops, best of 3: 1.68 ms per loop
100 loops, best of 3: 2 ms per loop
100 loops, best of 3: 2.05 ms per loop
100 loops, best of 3: 2.19 ms per loop
100 loops, best of 3: 2.53 ms per loop
100 loops, best of 3: 2.9 ms per loop
因此在这种情况下,明确的赢家是
f=operator.itemgetter(*l);f(m)
,并清除局外人:
映射(lambda:m[\uu],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)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l]  # list comprehension
%timeit list(map(m.__getitem__, l))
%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
%timeit list(map(m.get, l))
%timeit list(map(lambda _: m[_], l)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

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

速度比较:

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)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l]  # list comprehension
%timeit map(m.__getitem__, l)
%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
%timeit map(m.get, l)
%timeit map(lambda _: m[_], l)
1000 loops, best of 3: 1.14 ms per loop
1000 loops, best of 3: 1.68 ms per loop
100 loops, best of 3: 2 ms per loop
100 loops, best of 3: 2.05 ms per loop
100 loops, best of 3: 2.19 ms per loop
100 loops, best of 3: 2.53 ms per loop
100 loops, best of 3: 2.9 ms per loop
因此在这种情况下,明确的赢家是
f=operator.itemgetter(*l);f(m)
,并清除局外人:
映射(lambda:m[\uu],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)
%timeit list(itemgetter(*l)(m))
%timeit [m[_] for _ in l]  # list comprehension
%timeit list(map(m.__getitem__, l))
%timeit list(m[_] for _ in l)  # a generator expression passed to a list constructor.
%timeit list(map(m.get, l))
%timeit list(map(lambda _: m[_], l)
1.66 ms ± 74.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
2.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.58 ms ± 88.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.36 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.98 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.7 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.14 ms ± 62.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
因此,Python 3.6.4的结果几乎相同。

在不构建列表的情况下检索密钥:

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
与关闭后列表给出的顺序相匹配

在不构建列表的情况下检索密钥:

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
与列表给出的顺序相匹配的,请尝试以下操作:

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]
试试这个:

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]

熊猫在这方面做得非常优雅,尽管ofc列表的理解在技术上总是更像蟒蛇。我现在没有时间进行速度比较(我稍后会回来进行比较):


熊猫在这方面做得非常优雅,尽管ofc列表的理解在技术上总是更像蟒蛇。我现在没有时间进行速度比较(我稍后会回来进行比较):


@彼得·格洛珀你很困惑
items()
是首选,它不需要进行额外的查找,这里没有
len(mydict)*len(mykeys)
操作!(注意,我使用的是一套)@ÓscarLópez是的,你在检查字典的每个元素。iteritems在您需要它们之前不会生成它们,因此它可以避免构建中间列表,但您仍然可以为mydict中的每个k运行“k in mykeys”(order len(mykeys),因为它是一个列表)。完全不必要的是,与仅在mykeys上运行的更简单的列表理解相比。@inspectorG4dget@PeterdGlopper
mykeys
上的成员资格操作是按固定时间摊销的,我使用的是集合,而不是列表将OP的列表转换为集合至少使其线性化,但它在错误的数据结构上仍然是线性的,并且失去了顺序。考虑一下10K字典和MyK密钥中的2个密钥的情况。您的解决方案会进行10k集成员资格测试,而对于简单的列表理解,则会进行两次字典查找。一般来说,可以安全地假设键的数量将小于字典元素的数量,如果不是,您的方法将忽略重复的元素。@peterdegloper您感到困惑了
items()
是首选,它不需要进行额外的查找,这里没有
len(mydict)*len(mykeys)
操作!(注意,我使用的是一套)@ÓscarLópez是的,你在检查字典的每个元素。iteritems在您需要它们之前不会生成它们,因此它可以避免构建中间列表,但您仍然可以为mydict中的每个k运行“k in mykeys”(order len(mykeys),因为它是一个列表)。完全不必要的是,与仅在mykeys上运行的更简单的列表理解相比。@inspectorG4dget@PeterdGlopper
mykeys
上的成员资格操作是按固定时间摊销的,我使用的是集合,而不是列表将OP的列表转换为集合至少使其线性化,但它在错误的数据结构上仍然是线性的,并且失去了顺序。考虑一下10K字典和MyK密钥中的2个密钥的情况。与简单列表的两次字典查找相比,您的解决方案进行10k集成员资格测试