# How do I reorder and combine sublists based on sublist rankings given by another list?

I have two lists:

list = {{5, 6, 10}, {6}, {5, 9, 4, 8, 8}, {6, 4}, {9, 4, 5, 2, 10, 8,
10}, {4, 6, 6, 5, 7}, {3}, {8, 10, 8}, {9, 10}, {9, 10, 7, 7}}

sublistRank = {6, 5, 9, 6, 9, 5, 8, 6, 4, 8}


The values given in sublistRank are just arbitrary ranking values for each given sublist in list. The position of each sublistRank value corresponds to the sublist (in list) in the same position. For example, the first sublist of {5, 6, 10} has a ranking value of 6. The second sublist has a ranking value of 5, the third sublist has a ranking value of 9, etc. What I'd like to do is the following:

First I want to reorder sublistRank to be in numerical order; this is easily given by Sort[sublistRank] which yields the output:

sortedsublistRank= {4, 5, 5, 6, 6, 6, 8, 8, 9, 9}


I would then like to reorder list to be reflective of new ordering given to sublistRank. I'm not sure how to go about this, but the output would look like:

{{9, 10}, {6}, {4, 6, 6, 5, 7}, {5, 6, 10}, {6, 4}, {8, 10,
8}, {3}, {9, 10, 7, 7}, {5, 9, 4, 8, 8}, {9, 4, 5, 2, 10, 8, 10}}


For this step, the specific ordering of sublists which have the same rank do not matter. For example, the 2nd and 3rd sublists have a ranking value of 5, but it does not matter which sublist comes first, they'd be interchangeable.

Once I have the newly sorted list I'd then like to combine all sublists which have the same rank. This would yield the final desired output of:

{{9,10},{6,4,6,6,5,7},{5,6,10,6,4,8,10,8},{3,9,10,7,7},{5,9,4,8,8,9,4,5,2,10,8,10}}


Any advice on how to go about implementing either of the two steps would be greatly appreciated!

Combine them together

Transpose[{sublistRank, list}] // GatherBy[#, First] &

{
{{6, {5, 6, 10}}, {6, {6, 4}}, {6, {8, 10, 8}}},
{{5, {6}}, {5, {4, 6, 6, 5, 7}}},
{{9, {5, 9, 4, 8, 8}}, {9, {9, 4, 5, 2, 10, 8, 10}}},
{{8, {3}}, {8, {9, 10, 7, 7}}},
{{4, {9, 10}}}
}



then write a function to deal with data

f[x_] := {x // First // First, Last /@ x // Flatten}

{
{{6, {5, 6, 10}}, {6, {6, 4}}, {6, {8, 10, 8}}},
{{5, {6}}, {5, {4, 6, 6, 5, 7}}},
{{9, {5, 9, 4, 8, 8}}, {9, {9, 4, 5, 2, 10, 8, 10}}},
{{8, {3}}, {8, {9, 10, 7, 7}}},
{{4, {9, 10}}}
} // Map[f] // SortBy[#, First] &


Now we get

{{4, {9, 10}}, {5, {6, 4, 6, 6, 5, 7}}, {6, {5, 6, 10, 6, 4, 8, 10,
8}}, {8, {3, 9, 10, 7, 7}}, {9, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8,
10}}}


Take the last item of each item

{{4, {9, 10}}, {5, {6, 4, 6, 6, 5, 7}}, {6, {5, 6, 10, 6, 4, 8, 10,
8}}, {8, {3, 9, 10, 7, 7}}, {9, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8,
10}}} // Map[Last]


We get

{{9, 10}, {6, 4, 6, 6, 5, 7}, {5, 6, 10, 6, 4, 8, 10, 8}, {3, 9, 10,
7, 7}, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8, 10}}


Here is a way that hinges upon PositionIndex:

sublistRank // PositionIndex // KeySort // Values // Map[Catenate@list[[#]]&]

(* {{9, 10}, {6, 4, 6, 6, 5, 7}, {5, 6, 10, 6, 4, 8, 10, 8},
{3, 9, 10, 7, 7}, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8, 10}} *)


You can use the ResourceFunction GroupByList to combine lists with common ranks in an association:

assoc = ResourceFunction["GroupByList"][list, sublistRank, Flatten]


<|6 -> {5, 6, 10, 6, 4, 8, 10, 8}, 5 -> {6, 4, 6, 6, 5, 7}, 9 -> {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8, 10}, 8 -> {3, 9, 10, 7, 7}, 4 -> {9, 10}|>

Then, you can sort the keys and take the values:

Values @ KeySort @ assoc


{{9, 10}, {6, 4, 6, 6, 5, 7}, {5, 6, 10, 6, 4, 8, 10, 8}, {3, 9, 10, 7, 7}, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8, 10}}

You can use Ordering + Part to get list sorted by sublistRank (your first list):

orderedlist = list[[Ordering @ sublistRank]]

{{9, 10}, {6}, {4, 6, 6, 5, 7}, {5, 6, 10}, {6, 4}, {8, 10, 8}, {3},
{9, 10, 7, 7}, {5, 9, 4, 8, 8}, {9, 4, 5, 2, 10, 8, 10}}


Values @ GroupBy[Thread[{orderedlist, Sort @ sublistRank}], Last -> First, Flatten]


{{9, 10}, {6, 4, 6, 6, 5, 7}, {5, 6, 10, 6, 4, 8, 10, 8}, {3, 9, 10, 7, 7}, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8, 10}}

Alternatively, construct associations from sublistRank and list and use Merge:

assocs = Association /@ Thread[sublistRank -> list];

Catenate /@ Values @ KeySort @ Merge[Identity] @ assocs


{{9, 10}, {6, 4, 6, 6, 5, 7}, {5, 6, 10, 6, 4, 8, 10, 8}, {3, 9, 10, 7, 7}, {5, 9, 4, 8, 8, 9, 4, 5, 2, 10, 8, 10}}