12

I am trying to find the minimum values for all elements in a list of associations, below is an example

x = {<|"a"-> 4, "b"->9, "c"->15|>, <|"a"->21, "b"->11, "c"->1|>, <|"a"->12, "b"->3, "c"->21|>}

Required output for Min {<|"a"-> 2, "b"->3, "c"->1|>}

Required output for Max {<|"a"-> 21, "b"->11, "c"->15|>}

My attempt for Max: MaximalBy[Values]@x Result: {<|"a" -> 21, "b" -> 11, "c" -> 1|>}

for Min: MinimalBy[Values]@x Result: {<|"a" -> 4, "b" -> 9, "c" -> 15|>}

Is there an elegant way to achieve this result?

C. E.
  • 70,533
  • 6
  • 140
  • 264
  • 3
    I don't get it. How is the key a getting the value 2? That value does not appear for a in any of the associations. Similarly, why is the value of c not equal to 21 in the maximal result? – Shredderroy Dec 07 '18 at 06:30

5 Answers5

16

How about

a = {
    <|"a" -> 4, "b" -> 9, "c" -> 15|>,
    <|"a" -> 21, "b" -> 11, "c" -> 1|>,
    <|"a" -> 12, "b" -> 3, "c" -> 21|>
};

Merge[a, Min]

(*<|"a" -> 4, "b" -> 3, "c" -> 1|>*)

Merge[a, Max]

(*<|"a" -> 21, "b" -> 11, "c" -> 21|>*)

EDIT

Improved, as per Kuba's suggestion.

Shredderroy
  • 5,249
  • 17
  • 26
7
Random`Private`MapThreadMin[x]
Random`Private`MapThreadMax[x]

<|"a" -> 4, "b" -> 3, "c" -> 1|>

<|"a" -> 21, "b" -> 11, "c" -> 21|>

Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309
3
x = 
 {<|"a" ->  4, "b" ->  9, "c" -> 15|>, 
  <|"a" -> 21, "b" -> 11, "c" ->  1|>, 
  <|"a" -> 12, "b" ->  3, "c" -> 21|>};

Using MinMax and ArrayReduce (new in 12.2)

Columns

AssociationThread[{"a", "b", "c"} -> ArrayReduce[MinMax, Values[x], 1]]

<|"a" -> {4, 21}, "b" -> {3, 11}, "c" -> {1, 21}|>

Rows

AssociationThread[{"a", "b", "c"} -> ArrayReduce[MinMax, Values[x], 2]]

<|"a" -> {4, 15}, "b" -> {1, 21}, "c" -> {3, 21}|>

eldo
  • 67,911
  • 5
  • 60
  • 168
2

You may use Query and MinMax.

With x as in OP.

Query[Transpose /* Map[MinMax]]@x
<|"a" -> {4, 21}, "b" -> {3, 11}, "c" -> {1, 21}|>

You can produce a more descriptive result with AssociationThread.

res = Query[Transpose /* Map[AssociationThread[{"Min", "Max"}, MinMax@#] &]]@x
<|"a" -> <|"Min" -> 4, "Max" -> 21|>, 
  "b" -> <|"Min" -> 3, "Max" -> 11|>, 
  "c" -> <|"Min" -> 1, "Max" -> 21|>|>

Which you can then access by Key with Association's syntax sugar.

res["a", "Max"]
21

Hope this helps.

Edmund
  • 42,267
  • 3
  • 51
  • 143
2
x = {<|"a" -> 4, "b" -> 9, "c" -> 15|>,
     <|"a" -> 21, "b" -> 11, "c" -> 1|>,
     <|"a" -> 12, "b" -> 3, "c" -> 21|>};

Using Merge, Sort and Part:

Function[a, #[[{1, -1}]] &@Sort@a] /@ Merge[x, Identity]

(<|"a" -> {4, 21}, "b" -> {3, 11}, "c" -> {1, 21}|>)

Or using AssociationThread:

f = Function[a, #[[{1, -1}]] &@Sort@a];

For Columns:

f /@ AssociationThread[Keys@# -> Values@#] &@Merge[x, Identity]

(<|"a" -> {4, 21}, "b" -> {3, 11}, "c" -> {1, 21}|>)

For Rows:

f /@ AssociationThread[Keys@# -> Transpose@Values@#] &@Merge[x, Identity]

(<|"a" -> {4, 15}, "b" -> {1, 21}, "c" -> {3, 21}|>)

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44