根据值选择Python词典中的对象

时间:2012-11-19 06:42:37

标签: python indexing dictionary

我是Python的新手,决定从Matlab跳转。我试图找到问题的答案好几天但没有成功!

问题:我有一堆具有某些属性的对象。请注意,我不是在谈论这个词的编程意义上的对象和属性 - 我在谈论文字天文物体,我有不同类型的数值数据和物理属性。

在我的脚本循环中,我浏览目录中的每个源/对象,进行一些计算,并将结果粘贴在一个庞大的字典中。脚本的形式如下:

for i in range ( len(ObjectCatalogue) )

    calculate quantity1 for source i    

    calculate quantity2 for source i 

    determine attribute1 for source i 

    sourceDataDict[i].update( {'spectrum':quantity1} )

    sourceDataDict[i].update( {'peakflux':quantity2} )

    sourceDataDict[i].update( {'morphology':attribute1} )

所以,一旦我经历了一百多个来源,我可以说,访问光谱对象号。 20与spectrumSource20 = sourceData [20] ['spectrum']等。

我想要做的是能够根据关键字'形态'的值来选择字典中的所有对象。所以说'形态'的关键字可以采用'简单'或'复杂'的值。反正我是否可以在不诉诸循环的情况下做到这一点?即 - 我可以创建一个新词典,其中包含所有采用'形态'关键字'复杂'值的来源吗?

很难解释,但是使用我从Matlab习惯的逻辑索引,它看起来像

complexSourceDataDict = sourceDataDict[*]['morphology'=='complex']

(其中*表示字典中的所有对象)

无论如何 - 非常感谢任何帮助!

4 个答案:

答案 0 :(得分:3)

没有循环,没有。使用list comprehension,是:

complex = [src for src in sourceDataDict.itervalues() if src.get('morphology') == 'complex']

如果sourceDataDict恰好是一个列表,您可以放弃itervalues

complex = [src for src in sourceDataDict if src.get('morphology') == 'complex']

如果你考虑一下,评估一个*就意味着一个循环操作无论如何(假设它是有效的语法)。因此,您的诀窍是使用您正在使用的数据结构进行最有效的循环。

提高效率的唯一方法是提前索引所有数据对象“形态”键并使其保持最新状态。

答案 1 :(得分:1)

我相信你正在处理类似于以下的结构

sourceDataDict = [
    {'spectrum':1,
    'peakflux':10,
     'morphology':'simple'
    },
    {'spectrum':2,
    'peakflux':11,
     'morphology':'comlex'
     },
    {'spectrum':3,
    'peakflux':12,
     'morphology':'simple'
     },
    {'spectrum':4,
    'peakflux':13,
     'morphology':'complex'
     }
    ]

你可以使用List COmprehension

做类似的事情
>>> [e for e in sourceDataDict if e.get('morphology',None) == 'complex']
[{'morphology': 'complex', 'peakflux': 13, 'spectrum': 4}]

使用itertools.ifilter,您可以获得类似的结果

>>> list(itertools.ifilter(lambda e:e.get('morphology',None) == 'complex', sourceDataDict))
[{'morphology': 'complex', 'peakflux': 13, 'spectrum': 4}]

请注意,使用get代替索引是为了确保即使不存在键'形态',功能也不会失败。如果它确定存在,你可以重写上面的

>>> [e for e in sourceDataDict if e['morphology'] == 'complex']
[{'morphology': 'complex', 'peakflux': 13, 'spectrum': 4}]

>>> list(itertools.ifilter(lambda e:e['morphology'] == 'complex', sourceDataDict))
[{'morphology': 'complex', 'peakflux': 13, 'spectrum': 4}]

答案 2 :(得分:1)

没有一种直接的方法可以按顺序索引嵌套字典,就像你想要的语法一样。但是,有几种方法可以在Python中实现,具有不同的接口和性能特征。

表现最佳的解决方案可能是创建一个额外的字典,根据您关注的任何特征进行索引。例如,要查找'morphology'值为'complex'的值,您可能会这样:

from collections import defaultdict

# set up morphology dict (you could do this as part of generating the morphology)
morph_dict = defaultdict(list)
for data in sourceDataDict.values():
    morph_dict[data["morphology"]].append(data)

# later, you can access a list of the values with any particular morphology
complex_morph = morph_dict["complex"]

虽然这是高性能的,但是需要提前为所有内容设置反向索引可能会很烦人。另一种方法是使用列表推导或生成器表达式迭代字典并找到合适的值:

complex = (d for d in sourceDataDict.values() if d["morphology"] == "complex")

for c in complex:
    do_whatever(c)

答案 3 :(得分:0)

处理大量数据时,您可能希望将其存储在某个地方,因此某种数据库和ORM(例如),但后者是一个品味问题。 RDBMS的排序可能是解决方案。

对于原始python,除了像filter这样的功能例程之外,没有内置的解决方案。无论如何,你在某个步骤(隐式或不是)面临迭代。

最简单的方法是使用键作为属性值来保留额外的dict:

objectsBy['morphology'] = {'complex': set(), 'simple': set()}

for item in sources:
  ...
  objMorphology = compute_morphology(item)
  objectsBy['morphology'][objMorphology] += item
  ...