# Finding the maximum from a two dimensional list

I have a two-dimensional list where each value of $$x$$ can have many values of $$y$$. for example

{{1, 2}, {1, 3}, {1, 4}, {2, 2}, {2, 3}, {2, 4}, {2, 5}}


For each value of $$x$$, I have to find out the maximum value of $$y$$. So, the result will be like

{{1, 4}, {2, 5}}


I tried with Max, Short but was not able to run this in the loop.

Is there an efficient method?

Using GroupBy and MaximalBy

gpLst = GroupBy[lst, First, MaximalBy[#, Last][[1]] &]


<|1 -> {{1, 4}}, 2 -> {{2, 5}}|>

gpLst//Values


{{1, 4}, {2, 5}}

• Thanks @Anjan. It worked. Aug 8, 2020 at 6:09

Another one:

data = {{1, 2}, {1, 3}, {1, 4}, {2, 2}, {2, 3}, {2, 4}, {2, 5}};
GroupBy[data, First -> Last, Max]


<|1 -> 4, 2 -> 5|>

If you need the result as a list of pairs:

KeyValueMap[List, %]


{{1, 4}, {2, 5}}

• Yes, it also worked. Thanks Aug 9, 2020 at 16:16

Since you specified "Is there an efficient method?"

GatherBy[Sort@list, First][[All, -1]]


(here list is your list or variable the list is assigned to).

This should outperform the accepted solution by at least an order of magnitude.

Slightly more verbose, but even quicker:

With[{g = GatherBy[list, First]},
Transpose[{g[[All, 1, 1]], Max /@ g[[All, All, 2]]}]]


Here's a variation of @sjoerd's answer:

data={{1,2},{1,3},{1,4},{2,2},{2,3},{2,4},{2,5}};

ResourceFunction["GroupByList"][data[[All,2]],data[[All,1]],Max]


<|1 -> 4, 2 -> 5|>

For large datasets, this will be much faster than GroupBy:

data = RandomInteger[10000, {10^6, 2}];
r1=ResourceFunction["GroupByList"][data[[All,2]], data[[All,1]], Max];//AbsoluteTiming
r2=GroupBy[data, First->Last, Max];//AbsoluteTiming

r1===r2


{0.10384, Null}

{0.514609, Null}

True

This approach is also slightly faster than @ciao's.

list = {{1, 2}, {1, 3}, {1, 4}, {2, 2}, {2, 3}, {2, 4}, {2, 5}};
MaximalBy[#, Last] & /@ Split[list, #1[[1]] == #2[[1]] &]


Similar in spirit to Sjoerd Smit's answer: the wonderful thing about Mathematica's associations is that they automatically override earlier values in favor of later ones, which is exactly what you want! To demonstrate, let me shuffle your input:

data = {{1, 2}, {1, 4}, {2, 2}, {2, 4}, {2, 5}, {1, 3}, {2, 3}}


Converting into an association only keeps the last occurrence of each first coordinate:

AssociationThread @@ Transpose@data


returns <|1 -> 3, 2 -> 3|>. So we just need to sort first (fortunately Sort automatically checks second coordinates after it checks first coordinates):

AssociationThread @@ Transpose@Sort@data


returns <|1 -> 4, 2 -> 5|>. And if you want the answer as ordered pairs again, there's a function that does that:

KeyValueMap[List, AssociationThread @@ Transpose@Sort@data]


returns {{1, 4}, {2, 5}}.

• Thank you @Greg Aug 9, 2020 at 16:13