3
$\begingroup$

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?

$\endgroup$

2 Answers 2

3
$\begingroup$
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]]] 

enter image description here

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 
$\endgroup$
1
  • 1
    $\begingroup$ Hello, thanks for the answer, which fortunately works more like what I want; then, unfortunately, it seems no builtin function to work. $\endgroup$ Commented May 6, 2020 at 8:07
2
$\begingroup$

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}} 
$\endgroup$
4
  • $\begingroup$ 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. $\endgroup$ Commented May 6, 2020 at 7:48
  • $\begingroup$ @ΑλέξανδροςΖεγγ I do not understand, It gives same result as you show. Did you try {group1, group2} ? $\endgroup$ Commented May 6, 2020 at 7:53
  • $\begingroup$ I have to apologize, maybe I did not express myself very clearly. I have added additional information. Thanks a lot again. $\endgroup$ Commented May 6, 2020 at 7:53
  • $\begingroup$ Yes, I believe your code can give the right result. $\endgroup$ Commented May 6, 2020 at 7:54

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.