1
$\begingroup$

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.

$\endgroup$
4
  • 1
    $\begingroup$ KeySortBy[OddQ]@GatherBy[list, OddQ] $\endgroup$
    – b3m2a1
    Commented Nov 17, 2020 at 2:37
  • 1
    $\begingroup$ @b3m2a1, you meant GroupBy i think. $\endgroup$
    – kglr
    Commented Nov 17, 2020 at 4:01
  • $\begingroup$ @kglr oh I totally did. Missed the fact that the question was about GatherBy. Same approach will work with more post-processing or a different SortBy strategy $\endgroup$
    – b3m2a1
    Commented Nov 17, 2020 at 4:02
  • $\begingroup$ Could you please provide some examples to enrich the point you want to express? $\endgroup$ Commented Nov 17, 2020 at 4:07

2 Answers 2

1
$\begingroup$
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
$\endgroup$
0
$\begingroup$

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]

enter image description here

Table[sortedGatherBy[RandomSample @ list, Between[{3, 6}]], 10] // Grid

enter image description here

Table[sortedGatherBy[RandomSample @ list, Mod[#, 3] &], 10] // Grid

enter image description here

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 

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.