I want something like GatherBy[list, OddQ]
but it either consistently puts the odd elements first or consistently puts the even elements first, rather than have it depend on list
. The actual function I want to use it with is also boolean, although a more general solution that doesn't rely on this would be nice to have as well.
2 Answers
SeedRandom[1]
list = RandomSample@Range[10]
manyLists = Table[RandomSample@list, 10]
$$\left( \begin{array}{cccccccccc} 7 & 2 & 9 & 1 & 8 & 3 & 10 & 4 & 6 & 5 \\ 3 & 6 & 9 & 4 & 2 & 5 & 7 & 8 & 10 & 1 \\ 7 & 6 & 8 & 3 & 2 & 10 & 9 & 4 & 5 & 1 \\ 3 & 2 & 8 & 7 & 1 & 6 & 10 & 5 & 4 & 9 \\ 9 & 5 & 8 & 2 & 3 & 6 & 10 & 1 & 4 & 7 \\ 6 & 10 & 2 & 9 & 1 & 8 & 3 & 5 & 4 & 7 \\ 4 & 10 & 6 & 1 & 8 & 7 & 9 & 3 & 2 & 5 \\ 1 & 10 & 8 & 9 & 4 & 2 & 3 & 5 & 7 & 6 \\ 3 & 4 & 5 & 1 & 8 & 7 & 6 & 9 & 10 & 2 \\ 6 & 7 & 8 & 5 & 1 & 4 & 9 & 3 & 2 & 10 \\ \end{array} \right)$$
Last@
Reap[
Scan[
If [EvenQ[#],
Sow[#, even],
Sow[#, odd]
] &, #]] & /@ manyLists
$$\left( \begin{array}{cc} \{7,9,1,3,5\} & \{2,8,10,4,6\} \\ \{3,9,5,7,1\} & \{6,4,2,8,10\} \\ \{7,3,9,5,1\} & \{6,8,2,10,4\} \\ \{3,7,1,5,9\} & \{2,8,6,10,4\} \\ \{9,5,3,1,7\} & \{8,2,6,10,4\} \\ \{6,10,2,8,4\} & \{9,1,3,5,7\} \\ \{4,10,6,8,2\} & \{1,7,9,3,5\} \\ \{1,9,3,5,7\} & \{10,8,4,2,6\} \\ \{3,5,1,7,9\} & \{4,8,6,10,2\} \\ \{6,8,4,2,10\} & \{7,5,1,9,3\} \\ \end{array} \right)$$
Reaping {even,odd} will fix how the sublists are presented.
Last@
Reap[
Scan[
If [EvenQ[#],
Sow[#, even],
Sow[#, odd]
] &, #], {even, odd}] & /@ manyLists
If you wish to preserve the relative ordering of elements in each group, you can do:
ClearAll[sortedGatherBy]
sortedGatherBy = SortBy[#2 @* First] @ GatherBy[#, #2] &;
Examples:
SeedRandom[1]
list = RandomSample@Range[10]
{2, 5, 1, 10, 8, 6, 7, 9, 3, 4}
Table[sortedGatherBy[RandomSample @ list, OddQ], 10]
Table[sortedGatherBy[RandomSample @ list, Between[{3, 6}]], 10] // Grid
Table[sortedGatherBy[RandomSample @ list, Mod[#, 3] &], 10] // Grid
If it is ok to have the elements in each group sorted, then you can do
ClearAll[sortedGatherBy2]
sortedGatherBy2 = GatherBy[SortBy[#2]@#, #2] &;
Table[sortedGatherBy2[RandomSample @ list, OddQ], 10] // Grid
KeySortBy[OddQ]@GatherBy[list, OddQ]
$\endgroup$GroupBy
i think. $\endgroup$GatherBy
. Same approach will work with more post-processing or a differentSortBy
strategy $\endgroup$