# Divide a list into two sublists TakeDropwise, but according to inconsecutive positions

I can not make sure, but I have searched this website, there is not the same question as what I will ask below. If it turns out there indeed exists, please let me know, thanks a lot.

My question is not complicated, actually. Suppose I have a List of Length 32:

values = RandomInteger[9, 32];


A baby question

If I want to divide it into two groups, e.g., by naming that the 3rd to 6th elements are in Group I and the rest are in Group II, I can use TakeDrop to easily satisfy myself:

TakeDrop[values, {3, 6}]


The advantage of TakeDrop is that the user need not provide the information for Group II explicitly.

The real question

Well, what I really want to put into Group I, besides the 3rd to 6th elements, in the meanwhile includes also the 13th to 16th elements, namely, the position specification is not in a consecutive fashion. At first, I guessed TakeDrop maybe also to work, but did not find a way out. And what so far I can come up with is to use Part with Complement, something like:

{#[[{3, 4, 5, 6, 13, 14, 15, 16}]], #[[Complement[Range[32], {3, 4, 5, 6, 13, 14, 15, 16}]]]} &[values]


which, frankly speaking, I do not think very pretty, in that I have to write code to calculate the positions for Group II.

So, is there a way like TakeDrop working for my real question?

ClearAll[foldTakeDrop]
foldTakeDrop =  Fold[Function[{x, y}, {Join[#, First[x]], #2} & @@
TakeDrop[Last@x, y]], {{}, #}, Reverse[#2]] &;


Examples:

SeedRandom[1]
values = RandomInteger[9, 32]

{1, 4, 0, 7, 0, 0, 8, 6, 0, 4, 1, 8, 5, 1, 1, 1, 3, 2, 1, 6, 0, 2, 6, 4, 5,
4, 3, 0, 1, 3, 5, 3}

foldTakeDrop[values, {{3, 6}, {13, 16}}]

{{0, 7, 0, 0, 5, 1, 1, 1},
{1, 4, 8, 6, 0, 4, 1, 8, 3, 2, 1, 6, 0, 2, 6, 4, 5, 4, 3, 0, 1, 3, 5, 3}}

MapAt[Style[#, Red] &, values, List /@ Join[Range[3, 6], Range[13, 16]]]


foldTakeDrop[values, {{3, 6}, {13, 16}, {22, 28, 2}}]

{{0, 7, 0, 0, 5, 1, 1, 1, 2, 4, 4, 0},
{1, 4, 8, 6, 0, 4, 1, 8, 3, 2, 1, 6, 0, 6, 5, 3, 1, 3, 5, 3}}

MapAt[Style[#, Red] &, values,
List /@ Join[Range[3, 6], Range[13, 16], Range[22, 28, 2]]]


Update: Alternative methods:

ClearAll[thruExtractDelete, foldPairs]

thruExtractDelete = Through[{Extract, Delete}[#, List /@ Join @@ Range @@@ #2]] &;

foldPairs = {Flatten@Reverse@#[[All, All, 1]], #[[-1, -1, -1]]} &@
FoldPairList[TakeDrop, #, Reverse@#2, List] &;

foldPairs[values, {{3, 6}, {13, 16}}] ==
thruExtractDelete[values, {{3, 6}, {13, 16}}] ==
foldTakeDrop[values, {{3, 6}, {13, 16}}]

  True

foldPairs[values, {{3, 6}, {13, 16}, {22, 28, 2}}] ==
thruExtractDelete[values, {{3, 6}, {13, 16}, {22, 28, 2}}] ==
foldTakeDrop[values, {{3, 6}, {13, 16}, {22, 28, 2}}]

  True

• Hello, thanks for the answer, which fortunately works more like what I want; then, unfortunately, it seems no builtin function to work. Commented May 6, 2020 at 8:07

Group I, besides the 3rd to 6th elements, in the meanwhile includes also the 13th to 16th elements, namely, the position specification is not in a consecutive fashion

If I understand you right:

 values=RandomInteger[9,32]
(*{1,6,7,9,3,9,4,8,4,7,1,7,1,3,5,3,3,6,5,1,1,0,2,8,4,7,8,7,6,7,9,3}*)

p = Join[ Range[3, 6], Range[13, 16] ];
(*{3, 4, 5, 6, 13, 14, 15, 16}*)


The above are the positions of elements to delete. Part accepts non consecutive positions.

  group1 = values[[ p ]]

(* {7, 9, 3, 9, 1, 3, 5, 3} *)


To remove group1 from original list, one way is to use Delete. But Delete wants positions as {{1},{2},..} and not as {1,2,...}, so add extra {}

  group2 = Delete[values, List[#] & /@ p];
(*{1, 6, 4, 8, 4, 7, 1, 7, 3, 6, 5, 1, 1, 0, 2, 8, 4, 7, 8, 7, 6, 7, 9,  3}*)


And now

  {group1, group2}


gives

{{7, 9, 3, 9, 1, 3, 5, 3},
{1, 6, 4, 8, 4, 7, 1, 7, 3, 6, 5, 1, 1, 0, 2, 8, 4, 7, 8, 7, 6, 7, 9, 3}}

• Thanks for the quick response! I think your code understands what process to undergo and can obtain the right result. But it is not exactly what I want. Commented May 6, 2020 at 7:48
• @ΑλέξανδροςΖεγγ I do not understand, It gives same result as you show. Did you try {group1, group2} ? Commented May 6, 2020 at 7:53
• I have to apologize, maybe I did not express myself very clearly. I have added additional information. Thanks a lot again. Commented May 6, 2020 at 7:53
• Yes, I believe your code can give the right result. Commented May 6, 2020 at 7:54