比较具有较少循环的字典

时间:2018-06-21 14:47:21

标签: python dictionary

我有一本以字典为值的字典。以下是我的字典的结构

myD = {'key1': {'x' : 123, 'y' : 432},
       'key2': {'x' : 456, 'y' : 565},
       'key3': {'x' : 789, 'y' : 420},
       ...}

我需要比较该字典的值(如您所见,我在每个值中都有类似的字典结构)并生成以下输出。策略将遍历值字段中的每个词典,并为给定键选择最小值,然后将其插入新词典中。例如,如果我们考虑值字典中的x键,它的最小值为123。因此,我的新词典应具有x:123

my_newD =  {'x' : 123, 'y' : 420, ...}

我可以使用3个for循环来实现这一点,但是有什么优雅的方法可以减少for循环吗?

7 个答案:

答案 0 :(得分:4)

我想出了两个循环:

my_newD = {key: min(item[key] for item in myD.values()) 
           for key in  next(iter(myD.values()))}

编辑:按照@Andriy Makukha的建议,删除了对外部循环中'key1'的明确依赖

编辑2:将myD[list(myD.keys())[0]]替换为next(iter(myD.values()))
 不知道哪一个隐秘性较低,但使用nextiter确实看起来更有效。
感谢Leo K指出这一点!

答案 1 :(得分:4)

以下是使用button.disableProperty().bind(Bindings.size(tableView.getSelectionModel().getSelectedIndices()) .isNotEqualTo(1)); 的O(n)解决方案:

collections.defaultdict

答案 2 :(得分:1)

两个循环:

myD = {'key1': {'x' : 123, 'y' : 432},
       'key2': {'x' : 456, 'y' : 565},
       'key3': {'x' : 789, 'y' : 420}}

resD = {}
for key in myD:
    subD = myD[key]
    for k in subD:
        resD[k] = min(resD[k], subD[k]) if k in resD else subD[k]

print (resD)

输出:

{'x': 123, 'y': 420}

答案 3 :(得分:1)

使用pandas的另一种可能性(在优雅方面更好):

import pandas as pd
my_newD = pd.DataFrame(myD).min(axis=1).to_dict()

答案 4 :(得分:1)

这是我在O(n)中的解决方案

>>> from itertools import accumulate
>>>  min_t = lambda *t: [min(r) for r in zip(*t)]
>>> *_, min_vals = accumulate([v.values() for k,v in myD.items()], min_t)
>>> keys = next(iter(myD.values())).keys()
>>> dict(zip(keys, vals))
{'x': 123, 'y': 420}
>>> 

说明

>>> from itertools import accumulate
>>> 
>>> myD = {'key1': {'x': 123, 'y': 432}, 'key2': {'x': 456, 'y': 565}, 'key3': {'x': 789, 'y': 420}}
>>> 
>>> # Define a func to find min of tuples
>>> def min_t(*t):
...     return [min(r) for r in zip(*t)]
... 
>>> # Build the tuple 
>>> t = (v.values() for k,v in myD.items())
>>> *_, min_vals = accumulate(t, min_t)
>>> min_vals
[123, 420]
>>> 
>>> keys = next(iter(myD.values())).keys()
>>> keys
dict_keys(['x', 'y'])
>>> 
>>> 
>>> dict(zip(keys, vals))
{'x': 123, 'y': 420}
>>> 

或采用单行

>>> from itertools import accumulate
>>> from collections import deque
>>> dict(zip(next(iter(myD.values())).keys(), deque(accumulate((v.values() for k,v in myD.items()), lambda *t: [min(r) for r in zip(*t)]), maxlen=1).pop()))
{'x': 123, 'y': 420}

答案 5 :(得分:0)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="panel panel-warning">
  <div class="panel-heading">
    <span class="h4">Day - 1</span> |
    <span class="secTitle"><input name="sec[title]" value="Day 1" type="text"></span>
    <span class="pull-right panel-menu" data-secid="11">
      <a href="#" class="btn btn-primary btn-sm sec-form-btn">Save changes</a>
      <span class="fa fa-refresh fa-spin fa-1x fa-fw edit-sec-loader hidden"></span>
    </span>
  </div>
  <div class="panel-body">
    <div class="secDes mb10">
      <textarea name="sec[des]" class="form-control"></textarea>
    </div>
  </div>
</div>

答案 6 :(得分:0)

此动态代码适用于任意数量的变量。它的复杂度为O(M * N),其中M =要查找最小值的变量数,N = myD

中的键数
# here, M = 3, N = 3
myD = {'key1': {'x' : 123, 'y' : 432, 'z': 100},
       'key2': {'x' : 456, 'y' : 565, 'z': 99},
       'key3': {'x' : 789, 'y' : 420, 'z': 250}}
firstKey = "key1"

# assume firstKey has all the minimum entries
# use it as a base to compare all other values to
minD = {}
for (k,v) in myD[firstKey].items():
    minD[k] = v

items = myD.items()

#  find minimum of variable x, then y, then z
for variable in minD:
    print "Finding minimum of " + variable

    for key, dictionary in items:
        keyVal = dictionary[variable]
        if minD[variable] > keyVal:
            minD[variable] = keyVal

print minD # {'y': 420, 'x': 123, 'z': 99}