使用list获取列表的Python dict索引,与Perl哈希一样

时间:2013-12-12 03:51:36

标签: python perl dictionary hash

Perl有一个构造(称为"哈希切片"正如Joe Z指出的那样),用于索引到带有列表的哈希以获取列表,例如:

%bleah = (1 => 'a', 2 => 'b', 3 => 'c');
print join(' ', @bleah{1, 3}), "\n";

执行给出:

a c

我知道在Python中处理这个问题的最简单,最易读的方法是列表理解:

>>> bleah = {1: 'a', 2: 'b', 3: 'c'}
>>> print ' '.join([bleah[n] for n in [1, 3]])
a c

,因为:

>>> bleah[[1, 2]]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

我还有其他一些更好的方法吗?也许在Python3中,我还没有做过多少呢?如果没有,是否有人知道是否已经为此提交了PEP?我的google-fu无法找到。

&#34;它不是Pythonic&#34;:是的,我知道,但我喜欢它。它简洁易读,因为它永远不会是Pythonic索引到一个具有不可用类型的dict,让异常处理程序迭代索引而不是barfing不会打破大多数目前的代码。

注意:正如评论中指出的那样,这个测试用例可以重写为一个列表,完全避免使用dict,但我正在寻找一般解决方案。

4 个答案:

答案 0 :(得分:4)

我能想到的最好方法是使用itemgetter

from operator import itemgetter
bleah = {1: 'a', 2: 'b', 3: 'c'}
getitems = itemgetter(1, 3)
print getitems(bleah)

所以,如果你想传递一个索引列表,那么你可以解压缩参数,就像这样(感谢@koffein指出这一点:))

getitems = itemgetter(*[1, 3])

然后你可以join喜欢这个

print ' '.join(getitems(bleah))

或只是

print ' '.join(itemgetter(1, 3)(bleah))

答案 1 :(得分:1)

如果您的dict有连续的整数索引,那么您可以将其重建为列表并使用

bleah[1:3]

答案 2 :(得分:1)

目前,我正在评论中提出Hyperboreus的建议并覆盖__getitem__,但我仍然认为让它成为默认的dict行为是有意义的:

jcomeau@aspire:~$ cat /tmp/sliceable.py; echo ---; python /tmp/sliceable.py
'SliceableDict test'
import sys, os
class SliceableDict(dict):
 def __init__(self, d = {}):
  super(SliceableDict, self).__init__(d)
 def __getitem__(self, index):
  try:
   return super(SliceableDict, self).__getitem__(index)
  except TypeError:
   return [super(SliceableDict, self).__getitem__(x) for x in index]
 def __setitem__(self, index, value):
  try:
   super(SliceableDict, self).__setitem__(index, value)
  except:
   for i in range(len(index)):
    super(SliceableDict, self).__setitem__(index[i], value[i])
d = SliceableDict({1: 'a', 2: 'b', 3: 'c'})
print d[2]
print d[[1, 3]]
d[[1, 3]] = ['x', 'y']
print d
---
b
['a', 'c']
{1: 'x', 2: 'b', 3: 'y'}

(修改为根据上面的tobyink评论添加左值功能 - jc 2013-12-12)

答案 3 :(得分:0)

我会说这是略微更好,因为如果由于某种原因传递了一个未知密钥,你有一个默认值,它避免了不必要的内部列表和导入(如@thefourtheye的例子): / p>

bleah = {1: 'a', 2: 'b', 3: 'c'}
print(' '.join(bleah.get(i, '') for i in (1, 3)))

如果您只想要一个返回值列表:

list(bleah.get(i) for i in (1, 3))

此处无需默认值,因为get的默认值为NoneNone无法转换为字符串,这就是我在打印示例中传入空字符串的原因。