7
$\begingroup$

Suppose I have some list with duplicates by some condition and I want to take the duplicates and apply some function to choose which duplicate to keep. Is there an efficient way to apply this transformation?

To clarify here is an example. Consider a list with elements with duplicate first elements:

list={{2, 0.2}, {3, 0.}, {2, 0.1}, {4, 0.9}, {6, 0.3}, {3,  0.4}, {6, 0.3}}

Now I can apply, DeleteDuplicatesBy[list, #[[1]] &] and it will drop all the second instances of the duplicates in the list. But instead I want to do something else, say keep the duplicate with the maximum second value. This would look something like (my hypothetical function takes the arguments: list, function to find duplicates, function to act on duplicate list):

CombineDuplicateBy[list,#[[1]]&,MaximalBy[#,#[[2]]&]]
{{2, 0.2}, {4, 0.9},{3,  0.4}, {6, 0.3}}

Notice my hypothetical output deleted elements {3, 0.} and {6, 0.3} since they were duplicates and had a smaller (or equal) second value.

$\endgroup$
  • 6
    $\begingroup$ Look into GatherBy. In particular, MaximalBy[#, #[[2]] &, UpTo[1]] & /@ GatherBy[list, #[[1]] &]. $\endgroup$ – Rahul Jan 21 '18 at 22:10
  • 3
    $\begingroup$ You could also use SortBy, as in DeleteDuplicatesBy[Reverse@SortBy[list, Last], First]. $\endgroup$ – aardvark2012 Jan 21 '18 at 22:15
8
$\begingroup$

You could use GroupBy:

GroupBy[list, First, First@*MaximalBy[Last]]
Values @ %

<|2 -> {2, 0.2}, 3 -> {3, 0.4}, 4 -> {4, 0.9}, 6 -> {6, 0.3}|>

{{2, 0.2}, {3, 0.4}, {4, 0.9}, {6, 0.3}}

$\endgroup$
4
$\begingroup$

Also

KeyValueMap[{#, Max @ #2}&] @ Merge[Rule @@@ list, Identity]
Join @@ TakeLargestBy[Last, 1] /@ GatherBy[list, First]
Join @@ MaximalBy[#, Last, 1]& /@ GatherBy[list, First]

{{2, 0.2},{3, 0.4},{4, 0.9},{6, 0.3}}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.