Function that detects repetitions

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?

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.

• Thank You, your solution runs the fastest among others. – old Jul 5 at 9:13
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"}

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]