【问题标题】:Selecting objects in Python dictionaries based on values根据值在 Python 字典中选择对象
【发布时间】:2012-11-07 01:58:07
【问题描述】:

我是 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} )

因此,一旦我浏览了大约一百个来源,我就可以访问第 1 号物体的光谱。 20 with spectrumSource20 = sourceData[20]['spectrum'] etc.

我想要做的是能够根据关键字'morphology'的值选择字典中的所有对象说。所以说“形态学”的关键字可以采用“简单”或“复杂”的值。无论如何我可以在不诉诸循环的情况下做到这一点吗? IE。 - 我可以做一些事情,比如创建一个新字典,其中包含所有为“morphology”关键字取“complex”值的来源吗?

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

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

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

无论如何 - 任何帮助将不胜感激!

【问题讨论】:

  • 视情况而定。 sourceDataDict 是什么?它实际上是一本字典,还是一个包含字典的列表?
  • 您可能想查看名为 pandas 的库。它提供了一个表格数据结构,允许您随意访问。

标签: python indexing dictionary


【解决方案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}]

【讨论】:

  • 我并不是要吹毛求疵,但为什么建议每次使用 lambda 时都增加一个额外的函数调用开销?现在它必须调用调用 get 的 lambda
  • @jdi:使用get,将保证key不存在时key检索不会失败。万一确定,密钥将始终存在,则可以简单地使用字典索引。我不是 lambda 的忠实粉丝,但是来自 Matlab 的人确实很难理解 LC
  • 我同意。这就是我在自己的答案中使用get 的原因。但我是说你每次都必须调用第二个函数调用。拉姆达。我也在适当的地方使用 lambda。但这只是开销。对于get 的问题,您不需要使用None 参数。默认为None
【解决方案2】:

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

对于原始 python,除了像 filter 这样的函数式例程之外,没有内置的解决方案。无论如何,您在某个步骤(无论是否隐含)都会面临迭代。

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

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

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

【讨论】:

    【解决方案3】:

    没有一种直接的方法可以乱序索引嵌套字典,就像您想要的语法一样。但是,在 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)
    

    【讨论】:

      【解决方案4】:

      没有循环,没有。用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']
      

      如果您考虑一下,评估 * 无论如何都意味着在后台执行循环操作(假设它是有效的语法)。所以你的诀窍是用你正在使用的数据结构做最有效的循环。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-30
        相关资源
        最近更新 更多