1
$\begingroup$

How can I separate the odd terms in one array and the even terms in another array,i.e., go from

a={1,2,3,4}

to

aeven={2,4} and aodd={1,3}

I thought of:

a={1,2,3,4}

s={}

For[i = 1, i <= 4, i++, 
 If[EvenQ[a[[i]]] == True, AppendTo[a[[i]], s]]]

but it does not work.

Thankyou

$\endgroup$
1
  • $\begingroup$ Have a look at Cases and Select. $\endgroup$ Commented Feb 25, 2013 at 13:31

3 Answers 3

8
$\begingroup$
  GatherBy[a, OddQ]
  (* {{1, 3}, {2, 4}} *)

or

 Pick[a, # /@ a] & /@ {OddQ, EvenQ}

or

 Pick[a, OddQ /@ a, #] & /@ {True, False}

or

 Cases[a, _?#] & /@ {OddQ, EvenQ}

or

 Select[a, #] & /@ {OddQ, EvenQ}

or

 SplitBy[SortBy[a, EvenQ], EvenQ]
$\endgroup$
5
$\begingroup$

kguler already showed the primary methods so here are some secondary ones.

One for fun:

a = Range@10;

Reap[Sow[#, #~Mod~2] & /@ a, {0, 1}][[2, All, 1]]
{{2, 4, 6, 8, 10}, {1, 3, 5, 7, 9}}

And one for performance:

a = RandomInteger[1*^7, 1*^7];

With[{mask = BitAnd[a, 1]},
  {a[[ SparseArray[mask, Automatic, 1]["AdjacencyLists"] ]],
   a[[ SparseArray[mask]["AdjacencyLists"] ]]}
] // Timing // First
0.234

kguler's fastest method for comparison:

GatherBy[a, OddQ] // Timing // First
0.406

A fast method from Rojo for Mathematica versions 8+ (Pick was optimized after v7):

With[{mask = BitAnd[a, 1]}, Pick[a, mask, #] & /@ {0, 1}]
$\endgroup$
4
  • $\begingroup$ I'd stay with With[{mask = BitAnd[a, 1]}, Pick[a, mask, #] & /@ {0, 1}] $\endgroup$
    – Rojo
    Commented Feb 25, 2013 at 20:28
  • $\begingroup$ @Rojo That's significantly slower in version 7. Is it better in v8/v9? I recall Leonid saying that Pick had been optimized for packed arrays after v7. $\endgroup$
    – Mr.Wizard
    Commented Feb 26, 2013 at 2:07
  • $\begingroup$ GatherBy: 1.6s, yours: 0.73, with pick and BitAnd, 0.56. Both in v8 and v9 $\endgroup$
    – Rojo
    Commented Feb 26, 2013 at 12:30
  • $\begingroup$ @Rojo Okay, thanks. I added that to my answer. $\endgroup$
    – Mr.Wizard
    Commented Feb 26, 2013 at 13:14
0
$\begingroup$

I would go with one of the other options, but it can be done with Part and Span, as follows:

dat = Range[10];
{dat[[;; ;; 2]], dat[[2 ;; ;; 2]]}
(* {{1, 3, 5, 7, 9}, {2, 4, 6, 8, 10}} *)
$\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.