简体   繁体   English

字典中字典的Python列表理解?

[英]Python list comprehension for dictionaries in dictionaries?

I just learned about list comprehension, which is a great fast way to get data in a single line of code.我刚刚了解了列表推导式,这是一种在一行代码中快速获取数据的好方法。 But something's bugging me.但有些事情困扰着我。

In my test I have this kind of dictionaries inside the list:在我的测试中,我在列表中有这样的字典:

[{'y': 72, 'x': 94, 'fname': 'test1420'}, {'y': 72, 'x': 94, 'fname': 'test277'}]

The list comprehension s = [ r for r in list if r['x'] > 92 and r['x'] < 95 and r['y'] > 70 and r['y'] < 75 ] works perfectly on that (it is, in fact, the result of this line)列表推导s = [ r for r in list if r['x'] > 92 and r['x'] < 95 and r['y'] > 70 and r['y'] < 75 ]完美运行在那(实际上,这是这一行的结果)

Anyway, I then realised I'm not really using a list in my other project, I'm using a dictionary.无论如何,然后我意识到我并没有在我的另一个项目中真正使用列表,我使用的是字典。 Like so:像这样:

{'test1420': {'y': '060', 'x': '070', 'fname': 'test1420'}}

That way I can simply edit my dictionary with var['test1420'] = ...这样我就可以简单地用var['test1420'] = ...

But list comprehensions don't work on that!但是列表推导式对此不起作用! And I can't edit lists this way because you can't assign an index like that.而且我无法以这种方式编辑列表,因为您无法分配这样的索引。

Is there another way?还有其他方法吗?

You can do this:你可以这样做:

s = dict([ (k,r) for k,r in mydict.iteritems() if r['x'] > 92 and r['x'] < 95 and r['y'] > 70 and r['y'] < 75 ])

This takes a dict as you specified and returns a 'filtered' dict.这需要一个你指定的字典并返回一个“过滤”的字典。

If dct is如果dct

{'test1420': {'y': '060', 'x': '070', 'fname': 'test1420'},
 'test277': {'y': 72, 'x': 94, 'fname': 'test277'},}

Perhaps you are looking for something like:也许您正在寻找类似的东西:

[ subdct for key,subdct in dct.iteritems() 
  if 92<subdct['x']<95 and 70<subdct['y']<75 ]

A little nicety is that Python allows you to chain inequalities:一个小妙处是 Python 允许您链接不等式:

92<dct[key]['x']<95

instead of代替

if r['x'] > 92 and r['x'] < 95

Note also that above I've written a list comprehension, so you get back a list (in this case, of dicts).还要注意,上面我写了一个列表理解,所以你会得到一个列表(在这种情况下,是字典)。

In Python3 there are such things as dict comprehensions as well:在 Python3 中,还有诸如dict推导式之类的东西:

{ n: n*n for n in range(5) } # dict comprehension
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

In Python2 the equivalent would be在 Python2 中,相当于

dict( (n,n*n) for n in range(5) )

I'm not sure if you are looking for a list of dicts or a dict of dicts, but if you understand the examples above, it is easy to modify my answer to get what you want.我不确定您是在寻找字典列表还是字典字典,但是如果您了解上面的示例,很容易修改我的答案以获得您想要的。

Sounds like you want something like:听起来你想要这样的东西:

my_dict = {'test1420': {'y': '060', 'x': '070', 'fname': 'test1420'},
           'test277' : {'y': '072', 'x': '094', 'fname': 'test277'}}


new_dict = dict((k,v) for k,v in my_dict.items() 
                    if 92 < int(v['x']) < 95 and 70 < int(v['y']) < 75)

Some notes on this code:关于此代码的一些说明:

  1. I'm using a generator expression instead of a list comprehension我正在使用生成器表达式而不是列表理解
  2. Python lets you combine inequality tests as low < value < high Python 允许您将不等式测试组合为low < value < high
  3. The dict() constructor takes an iterable of key/value tuples to create a dictionary dict() 构造函数采用可迭代的键/值元组来创建字典

You can get a list of the values of a dictionary d with d.values() .您可以使用d.values()获取字典 d 的值列表。 Your list comprehension should work using that, although I'm a little unclear what exactly you want the output to be.你的列表理解应该使用它,尽管我有点不清楚你到底想要什么输出。

Is there another way?还有其他方法吗?

Why not consider the use of some lightweight objects?为什么不考虑使用一些轻量级的对象呢?

You can still use list comprehensions for gathering or filtering the objects, and gain a lot in clarity / extensibility.仍然可以使用列表推导式来收集或过滤对象,并在清晰度/可扩展性方面获得很多好处。

>>> class Item(object):
...     def __init__(self, x, y, name):
...         self.x = x
...         self.y = y
...         self.name = name
... 
>>> list_items = []
>>> list_items.append(Item(x=70, y=60, name='test1420'))                        
>>> list_items.append(Item(x=94, y=72, name='test277'))                         
>>> items_matching = [item for item in list_items 
                      if 92 < item.x < 95 and 70 < item.y < 75]
>>> for item in items_matching:
...     print item.name
... 
test277
>>> first_item = items_matching[0]
>>> first_item.x += 50
>>> first_item.x
144

In Python 3 you can use dict comprehension which can be an even shorter solution:在 Python 3 中,您可以使用 dict comprehension,它可以是一个更短的解决方案:

{key_expression(item) : value_expression(item) for item in something if condition}
  1. In case you want to filter a dictionary as in the original question:如果您想像原始问题一样过滤字典:

     mydict = {'test1': {'y': 60},'test2': {'y': 70},'test3': {'y': 80}} s = {k : r for k,r in mydict.items() if r['y'] < 75 } > {'test1': {'y': 60}, 'test2': {'y': 70}}
  2. Or we can even create something out of a list or range.或者我们甚至可以在列表或范围之外创建一些东西。 Eg if we want a dictionary with all odd square numbers:例如,如果我们想要一个包含所有奇数平方数的字典:

     {i : i**2 for i in range(11) if i % 2 == 1} > {1: 1, 3: 9, 5: 25, 7: 49, 9: 81}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM