# 来自 python defaultdictionary 的给定键的最小值

I got a `defaultdict` with lists as values and tuples as keys (`ddict` in the code below). I want to find the min and max of values for a given set of keys. The keys are given as a numpy array. The numpy array is a 3D array containing the keys. Each row of the 3D array is the block of keys for which we need to find the `min` and `max` i.e. for each row we take the corresponding 2D array entries, and get the values corresponding to those entries and find the `min` and `max` over those values. I need to do it for all the rows of the 3D array.

``````from operator import itemgetter
import numpy as np

ddict =  {(1.0, 1.0): [1,2,3,4], (1.0, 2.5): [2,3,4,5], (1.0, 3.75): [], (1.5, 1.0): [8,9,10], (1.5, 2.5): [2,6,8,19,1,31], (1.5,3.75): [4]}
indA = np.array([ [ [( 1.0, 1.0), ( 1.0, 3.75)], [(1.5,1.0), (1.5,3.75)] ], [ [(1.0, 2.5), (1.5,1.0)], [(1.5, 2.5), (1.5,3.75)] ] ])

mins = min(ddict, key=itemgetter(*[tuple(i) for b in indA for i in b.flatten()]))
maxs = max(ddict, key=itemgetter(*[tuple(i) for b in indA for i in b.flatten()]))
``````

I tried the above code to get the output of

`min1 = min([1,2,3,4,8,9,10,4])` & `min2 = min([2,3,4,5,8,9,10,2,6,8,19,1,31,4])` and `max1= max([1,2,3,4,8,9,10,4])` & `max2 = max([2,3,4,5,8,9,10,2,6,8,19,1,31,4])`

I want to calculate the `min` and `max` for every 2D array in the numpy array. Any workaround ? Why my code is not working ? It gives me error `TypeError: tuple indices must be integers or slices, not tuple`

## 推荐答案

Here is what I think you're after:

``````import numpy as np

# I've reformatted your example data, to make it a bit clearer
# no change in content though, just different whitespace
# whether d is a dict or defaultdict doesn't matter
d = {
(1.0, 1.0): [1, 2, 3, 4],
(1.0, 2.5): [2, 3, 4, 5],
(1.0, 3.75): [],
(1.5, 1.0): [8, 9, 10],
(1.5, 2.5): [2, 6, 8, 19, 1, 31],
(1.5, 3.75): [4]
}

# indA is just an array of indices, avoid capitals in variable names
indices = np.array(
[
[[(1.0, 1.0), (1.0, 3.75)], [(1.5, 1.0), (1.5, 3.75)]],
[[(1.0, 2.5), (1.5, 1.0)], [(1.5, 2.5), (1.5, 3.75)]]
])

for group in indices:
# you flattened each grouping of indices, but that flattens
# the tuples you need intact as well:
print('not: ', group.flatten())
# Instead, you just want all the tuples:
print('but: ', group.reshape(-1, group.shape[-1]))

# with that knowledge, this is how you can get the lists you want
# the min and max for
for group in indices:
group = group.reshape(-1, group.shape[-1])
values = list(x for key in group for x in d[tuple(key)])
print(values)

# So, the solution:
result = [
(min(vals), max(vals)) for vals in (
list(x for key in grp.reshape(-1, grp.shape[-1]) for x in d[tuple(key)])
for grp in indices
)
]
print(result)
``````

Output:

``````not:  [1.   1.   1.   3.75 1.5  1.   1.5  3.75]
but:  [[1.   1.  ]
[1.   3.75]
[1.5  1.  ]
[1.5  3.75]]
not:  [1.   2.5  1.5  1.   1.5  2.5  1.5  3.75]
but:  [[1.   2.5 ]
[1.5  1.  ]
[1.5  2.5 ]
[1.5  3.75]]
[1, 2, 3, 4, 8, 9, 10, 4]
[2, 3, 4, 5, 8, 9, 10, 2, 6, 8, 19, 1, 31, 4]
[(1, 10), (1, 31)]
``````

That is, `[(1, 10), (1, 31)]` is the result you are after, `1` being the minimum of the combined values of the first group of indices, `10` the maximum of that same group of values, etc.

Some explanation of key lines:

``````values = list(x for key in group for x in d[tuple(key)])
``````

This constructs a list of combined values by looping over every pair of key values in `group` and using them as an index into the dictionary `d`. However, since key will be an `ndarray` after the reshaping, it is passed to the `tuple()` function first, so that the `dict` is correctly indexed. It loops over the retrieved values and adds each value `x` to the resulting list.

The solution is put together in a single comprehension:

``````[
(min(vals), max(vals)) for vals in (
list(x for key in grp.reshape(-1, grp.shape[-1]) for x in d[tuple(key)])
for grp in indices
)
]
``````

The outer brackets indicate that a list is being constructed. `(min(vals), max(vals))` is a tuple of min and max of `vals`, and `vals` loops over the inner comprehension. The inner comprehension is a generator (with parentheses instead of brackets) generating the lists for each group in `indices`, as explained above.