Gathering of list
As requested by the OP:
Normal[GroupBy[data, First -> Last]] /. Rule -> List
{{"bird", {1, 8, 14}}, {"cow", {2, 3, 5, 6, 7}}, {"dog", {4, 9, 11, 13}},
{"cat", {10}}, {"pig", {12, 15}}}
The handy bit here is the second argument of GroupBy[]
:
GroupBy[data, First -> Last]
<|"bird" -> {1, 8, 14}, "cow" -> {2, 3, 5, 6, 7}, "dog" -> {4, 9, 11, 13},
"cat" -> {10}, "pig" -> {12, 15}|>
which transforms the values associated with the keys into the desired list of numbers. Contrast this with a plain GroupBy[data, First]
.
As noted by multiple people, a more compact version is
List @@@ Normal[GroupBy[data, First -> Last]]
Tom in a comment below gives a slicker version:
KeyValueMap[List, GroupBy[data, First -> Last]]
The GatherBy[]
approach presented by the OP can also be written as
Append[Union[#[[All, 1]]], #[[All, 2]]] & /@ GatherBy[data, First]
or as
Append @@ MapAt[Union, Transpose[#], 1] & /@ GatherBy[data, First]
I think this is one of the simplest here, both conceptually and in code:
Reap[Sow @@@ Reverse[data, {2}], _, List][[2]]
MapAt[#[[1]]&, Transpose/@ GatherBy[data, First], {;; , 1}]
{{"bird", {1, 8, 14}}, {"cow", {2, 3, 5, 6, 7}}, {"dog", {4, 9, 11, 13}}, {"cat", {10}}, {"pig", {12, 15}}}
Edit Corrected by murray, aka OP:
MapAt[Last, Transpose/@ GatherBy[data, First], {;; , 1}]
Edit2 Just for the ad hoc case with specific numeration PositionIndex
:
List @@@ Normal @ PositionIndex[data[[All, 1]]]