4
$\begingroup$

I have a large list of 2-tuples and I need a function that lists first values that have at least one repeated second value. Small example:

Function[{{"name1",4},{"name2",5.4},{"name7",4},{"name9",-3},
   {"name11",4},{"name6",-3},{"name15",4.1}] =
 {"name1","name7","name9","name11","name6"}

How to do it efficiently?

$\endgroup$
5
$\begingroup$

Here's one way to solve your problem. First, let

list1 = {{"name1",4},{"name2",5.4},{"name7",4},{"name9",-3},{"name11",4},
         {"name6",-3},{"name15",4.1}};

then

Sort[Transpose[Catenate[Select[GatherBy[list1, Last], Length[#] > 1 &]]][[1]]]

I don't know if that is efficient enough for you, but will be interested to see how it compares with other proposed solutions.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank You, your solution runs the fastest among others. $\endgroup$ – user65832 Jul 5 '19 at 9:13
7
$\begingroup$
list = {{"name1", 4}, {"name2", 5.4}, {"name7", 4}, {"name9", -3}, {"name11", 4},
     {"name6", -3}, {"name15", 4.1}};

You can also use Counts and Cases:

counts = Counts[list[[All, 2]]];
Cases[{a_, _?(counts[#] > 1 &)} :> a] @ list

{"name1", "name7", "name9", "name11", "name6"}

And an alternative way to use GatherBy + Select combination:

list[[Join @@ 
  Select[Length @ # > 1 &] @
    GatherBy[Range @ Length @ list, list[[#, 2]] &], 1]]

{"name1", "name7", "name11", "name9", "name6"}

| improve this answer | |
$\endgroup$
6
$\begingroup$

Applying GroupBy to your test list:

GroupBy[testlist, Last -> First]

<|4 -> {"name1", "name7", "name11"}, 5.4 -> {"name2"}, -3 -> {"name9", "name6"}, 4.1 -> {"name15"}|>

It remains to select values with the length larger than one. This can be done, for example like this:

func2[l_] := Flatten[Values[Select[GroupBy[l, Last->First], (Length[#]>1)&]]]

func2[testlist]

{"name1", "name7", "name11", "name9", "name6"}

Same concept as a composition of functions:

func = Flatten@*Values@*Select[GreaterThan[1]@*Length]@*GroupBy[Last->First]
| improve this answer | |
$\endgroup$

Your Answer

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