【问题标题】:Filter dict by certain values按某些值过滤 dict
【发布时间】:2014-09-25 18:26:46
【问题描述】:

我有一个像这样的字典

db = {
'ObjectID': ['-1', '6', '10', '13', '13', '13', '-1', '-1', '-1', '-1', '-1', '-1'], 
'Test_value': ['25', '0,28999999', '100,00000000', 'Geometry', '126641,847400000000', '473106,185600000030', ' ', ' ', ' ', ' ', ' ', ' '], 
'Has_error': ['true', 'true', 'true', 'true', 'true', 'true', 'false', 'false', 'false', 'false', 'false', 'false'], 
'Message': ['Table row counts are different', 'ObjectID 6 is different for Field DIKTE_BRUGDEK', 'ObjectID 10 is different for Field RICHTING_1',                'ObjectID 13 is different for Field GEOMETRIE', 'ObjectID 13 is different for Field X', 'ObjectID 13 is different for Field Y', 'Shape types are the          same', 'Feature types are the same', 'Feature class extents are the same', 'GeometryDefs are the same', 'Field properties are the same', 'Spatial             references are the same'], 'Identifier': ['Table', 'FeatureClass', 'FeatureClass', 'FeatureClass', 'FeatureClass', 'FeatureClass', 'FeatureClass',            'FeatureClass', 'FeatureClass', 'GeometryDef', 'Field', 'SpatialReference'], 
'Base_value': ['23', '0,19000000', '394,00000000', 'Geometry', '126530,700000000000', '473095,700000000010', ' ', ' ', ' ', ' ', ' ', ' ']}

我想根据“ObjectID”列表中的条目将其分解为一个较小的子集,即-1。 我的第一次尝试是建立一个值的索引,例如:

filter_ind = []
for k,v in db.iteritems():
    for i in xrange(len(v)):
            if (k == 'ObjectID') and (int(v[i]) != -1):
                filter_ind.append(i) 

然后我尝试构建一个新的字典,使用 filter_ind 作为排序过滤器: dict((k,v[i]) for i in filter_ind for k, v in db.iteritems())

我得到的只是最后一场比赛,因为 v 不再是一个列表: {'ObjectID':'13','Test_value':'473106,185600000030','Has_error':'true', 'Message':'ObjectID 13 is different for Field Y', 'Identifier':'FeatureClass','Base_value': '473095,700000000010'}

问题:是否有另一种方法可以根据自身内部的特定值过滤 dict?如果这被认为是一种相对直接的方法,那么使用索引作为过滤器来创建新字典的聪明方法是什么?已经谢谢了。

【问题讨论】:

  • 正如我所说,值列表应该只包含基于db ['ObjectID'] != -1(即[1,2,3,4,5])索引的条目。
  • 谢谢,我最初的解释是你想要一个字典列表,比如[{'ObjectID': '6', ...}, {'ObjectID': '10', ...}, ...]

标签: python dictionary filtering


【解决方案1】:

我认为你有点过于复杂了。首先,不需要嵌套循环。您可以通过这种方式获得所需的索引:

oids = db['ObjectID']
for i, id in enumerate(oids):
    if id != -1
        filter_ind.append(i) 

或者更简洁,

filter_ind = [i for i, id in enumerate(oids) if id != '-1']

然后您可以使用 id 来过滤各个列表:

dict((key, [val[i] for i in filter_ind]) for key, val in db.iteritems())

【讨论】:

  • 有同样的印象...:-/ 这是非常直接的。谢谢!
  • @larsvegas,我会简单地补充一下,这是一本有点非传统的字典。您是否考虑过将其构建为字典字典,使用 id 作为主键并将文件名作为内部字典的键?
  • 还没有考虑,没有...我只是从dbf中读取这样的数据,所以我想保持列,行结构完整。
【解决方案2】:

这是另一种选择:

from operator import itemgetter

iget = itemgetter(*(i for i, id in enumerate(db['ObjectID']) if int(id) != -1))
result = dict((k, list(iget(v))) for k, v in db.items())

【讨论】:

  • 我想这是高级选项,至少对我来说不太可读。 *-operator 在这里做什么?是算子吗?
  • 这里的* 有时称为splat 运算符,在文档中称为Unpacking Argument Lists。基本上foo(*[1, 2, 3]) 等价于foo(1, 2, 3)operator.itemgetter() 函数接受任意数量的索引(或键)并返回可用于过滤序列(或映射)以仅获取指定元素的函数。
【解决方案3】:

这是我做的:

new_db=db.copy()
fltr=[x=='-1' for x in new_db['ObjectID']] #Not actually necessary, but makes the code a little more readable

for k,v in new_db.items():
    new_db[k]=[x for i,x in enumerate(new_db[k]) if fltr[i]]  #replace old lists with new filtered ones.

这与 senderle 发布的答案非常相似(我认为)。我使用布尔列表,而另一个答案使用索引。我的可能效率不高,但我更容易阅读/理解。

【讨论】:

    【解决方案4】:

    如果您使用的是 2.7:

    from itertools import compress
    indexes = [(x != -1) for x in db['ObjectID']]
    result = dict((k, compress(v, indexes)) for k, v in db.iteritems())
    

    【讨论】:

      【解决方案5】:

      这其实是很少见的可以使用itertools.compress的场合:

      from itertools import compress
      
      sels = [x != '-1' for x in db['ObjectID']]
      comp = {key: list(compress(vals, sels)) for key, vals in db.items()}
      

      【讨论】:

        【解决方案6】:

        我喜欢这个:

        [dict(zip(db.keys(),e)) for e in zip(*db.values()) if e[0]!='-1']
        

        它返回一个字典列表,不包括带有 -1 的字典。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-12-20
          • 2020-08-22
          • 2013-05-05
          • 2021-11-24
          • 2022-08-19
          • 1970-01-01
          • 2013-04-02
          • 2021-06-27
          相关资源
          最近更新 更多