# Gather all elements of a list defined by a list of ranges

I am trying to do the following:

I have a list, say:

a = {{1}, {2}, {3}, {4},{5},{6}}


and a list which specifies the range:

range = {{1, 3}, {4, 6}};


Now I would like to receive a list, which gathers elementwise all list elements of list a within the range of "range".

The result should be:

result = {{1,2,3},{4,5,6}}


What I tried:

t = {};
result = AppendTo[t, a[[#[], #[] ]] ] & /@ a


But it does not work.

• Although not answering your specific question, TakeDrop might be worth considering? TakeDrop[Flatten@a, 3] or TakeDrop[Flatten@a, First@range] Oct 25 '17 at 22:19

I think this is what you want:

Flatten[Take[a, #]] & /@ range


{{1,2,3},{4,5,6}}

result = Range @@@ range


{{1, 2, 3}, {4, 5, 6}}

Or more like your own code:

a = {{1}, {2}, {3}, {4}, {5}, {6}};
range = {{1, 3}, {4, 6}};
t = {};
result = Last[AppendTo[t, a[[#[] ;; #[], 1]]] & /@ range]

• Thanks a lot ! Why are you not using a in the first solution ? Oct 25 '17 at 16:29
• How would you do it, if a would be: a = {1, 2, 3, 4, 5, 6} ? Oct 25 '17 at 16:36
• @totyped For a = {{1}, {2}, {3}, {4}, {5}, {6}} you want the output {{1,2,3}, {4,5,6}} and for a = {1, 2, 3, 4, 5, 6} i don't understand how the output should change. What should output be? Oct 25 '17 at 16:44
• The output should be the same. Oct 25 '17 at 16:49
• @totyped That's why i don't use a in the first one. I the second you would need to remove , 1 Oct 25 '17 at 16:50
a = {{1}, {2}, {3}, {4}, {5}, {6}} // Flatten;

range = {{1, 3}, {4, 6}};

Pick[a, #] & /@ Outer[IntervalMemberQ[Interval[#1], #2] &,
range, a, 1]

(* {{1, 2, 3}, {4, 5, 6}} *)


I may be missing the point here, but it seems to me that there is some ambiguity in what constitutes a generalization of the question, and the answers posted appear to be generalizing in quite different ways and/or answering quite different questions.

This ambiguity stems from the nice sequential ordering of a and range, but one interpretation (possibly just mine) of the requirement

"I would like to receive a list, which gathers elementwise all list elements of list a within the range of range"

can be better illustrated by the following less nice example:

SeedRandom
a = Sort@RandomSample[List /@ Range, 10]
range = {{1, #}, {# + 1, 20}} &@ RandomInteger[{Min[a] + 1, Max[a] - 2}]

(* {{1}, {2}, {6}, {8}, {9}, {11}, {13}, {16}, {17}, {19}} *)

(* {{1, 5}, {6, 20}} *)


The "correct" output (again, according to me, and possibly not to the OP) should be

(* {{1, 2}, {6, 8, 9, 11, 13, 16, 17, 19}} *)


which (as far as I can tell) only @Nasser's Map and @BobHanlon's Pick provide. (Obviously, this is still "nice" to some extent -- I'm assuming a is an ordered list of integers, range is composed of only two intervals, etc..)

Here's an assortment of other functions which provide the "correct" answer:

Pick[Flatten[a], UnitStep[Flatten[a] - range[[2, 1]]], #] & /@ {0, 1}

TakeDrop[#, First@FirstPosition[#, x_ /; x > range[[1, 2]]] - 1] &@ Flatten[a]

GatherBy[Flatten[a], # <= range[[1, 2]] &]

Last@Reap[Scan[Sow[#, # <= range[[1, 2]]] &, Flatten[a]]]


(They also give the right output for the example in the question.)

• Indeed, I open a question and see instead of vtc because unclear, lots of answers, yet I am completely baffled as to op's actual intent. Why must a be a nested list, for example? Oct 26 '17 at 5:46
Flatten[a[[Span @@ #]]] & /@ range


{{1, 2, 3}, {4, 5, 6}}

or

Extract[a, List /@ (Range @@@ range), Flatten]


{{1, 2, 3}, {4, 5, 6}}

Further examples:

Extract[Range[0, 100, 10], List /@ (Range @@@ range), Flatten]


{{0, 10, 20}, {30, 40, 50}}

Extract[CharacterRange["A","Z"], List /@ (Range @@@ range), Flatten]


{{"A", "B", "C"}, {"D", "E", "F"}}

Using Intersection

a = Flatten@{{1}, {2}, {3}, {4}, {5}, {6}};
range = Range @@@ {{1, 3}, {4, 6}};


And now

Map[Intersection[a, #] &, range] Lets say your data now becomes

a = Flatten@{{1}, {2}, {5}, {6}};


Then

Map[Intersection[a, #] &, range] 