# Drop From One list and Take in other list

Suppose I have a list,

list = Table[{n}, {n, 1, 5}]
(*list = {{1},{2},{3},{4},{5}}*)


and I want to remove all values from this list that are greater than 3, so that I get

newlist = {{1}, {2}, {3}}


But the other values should be saved in another list called the drop list to this below as shown

droplist = {{4},{5}}


TakeDrop[sort = Sort[list], LengthWhile[sort, First[#] < 4 &]]


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

As the reminder of Pillsy's answer here

GatherBy[list, 3 < First[#1] &]


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

You can use GroupBy and Lookup to make sure that the two returned lists are in the order you expect:

{newlist, droplist} =
Lookup[GroupBy[list, 3 < First[#1] & ], {False, True}, {}];


The third argument to Lookup makes sure an empty list is returned if there aren't any True or False elements, instead of a potentially annoying Missing object.

newlist
(* {{1}, {2}, {3}} *)

droplist
(* {{4}, {5}} *)

• +1 If needed, we could account for one of the lists being empty by adding {} as the third default argument to Lookup. This is my favourite answer so far. Apr 29, 2017 at 3:18
– yode
Apr 29, 2017 at 4:25
• @yode the only problem with that simplification is it won't always return the lists in the same order, so you won't always know which is newlist and which is droplist. Apr 29, 2017 at 20:22
• @WReach good point, and a nice change! edited. Apr 29, 2017 at 20:22

one option might be to use DeleteCases and then use Complement

list = Table[{n}, {n, 1, 5}]
newList = DeleteCases[list, {x_} /; x > 3]


droppedList = Complement[list, newList]


• Out of curiosity, how is the first part better than newList = Select[list, First[#] > 3&]? Apr 29, 2017 at 0:23
• @IgorRivin in Mathematica, the rule of thumb is: there are at least 10 different ways to do same thing. Now which one of these 10 ways is "better" than the other left to the reader to decide and can depend on many things. They can also all be equally "good". Apr 29, 2017 at 0:40
• There could be a major performance difference. In fact, there is none between our two ways (for al list of length 5000000, your method takes 4.02137 seconds, and mine 4.36038 seconds (both pretty pathetic on modern hardware). By contrast, WReach's method (in the other answer) takes 8.75143 seconds. Apr 29, 2017 at 0:51
• @IgorRivin yes. Performance can always be a deciding factor on which method to use. Apr 29, 2017 at 0:53

Here is a way that uses Query:

{dropList, newList} = list // Query[Select /@ {#, Not@*#}] &[#[[1]] > 3 &];

newList
(* {{1}, {2}, {3}} *)

dropList
(* {{4}, {5}} *)


... and another way that uses a double Reap to collect values sown from a single Scan:

Reap[Reap[Scan[Sow[#, #[[1]]>3]&, list], False, (newList=#2)&], True, (dropList=#2)&];

• I thought Query[] was only supposed to work with Dataset?! Apr 29, 2017 at 1:04
• @IgorRivin It is the other way around... Dataset has a short form for expressing queries :) Apr 29, 2017 at 1:11
• This is what the documentation says: Query[Subscript[operator, 1],Subscript[operator, 2],\[Ellipsis]] represents a query that can be applied to a Dataset object, in which the successive Subscript[operator, i] are applied at successively deeper levels. Apr 29, 2017 at 1:37
• There seem to be no non-Dataset examples... Apr 29, 2017 at 1:37
• @IgorRivin It also says: Query can operate on a Dataset object or an arbitrary nested expression consisting of lists and associations. In fact, it can operate upon any expression as it is simply an alternate syntax for composing operators -- as it can be seen as a generalization of Part. Virtually none of the examples under Query involve Dataset (there is one in the last section). Apr 29, 2017 at 3:13

In:

xss = Range[5] // Map[List]
yss = xss // Select[# <= 3 & @@ # &]
zss = Complement[xss, yss]


Out:

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

Pick[list, (# > 3) & @@@ list, #] & /@ {False, True}


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

This approach uses SequenceCases

SequenceCases[list, {{_?(# <= 3 &)} ..} | {{_?(# > 3 &)} ..}]
(* {{{1}, {2}, {3}}, {{4}, {5}}} *)

{newList, dropList} = Through[{#[#[[1]] <= 3 &], #[#[[1]] > 3 &]}[lst]] & @ Select


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

• Note the element should be #<3&
– yode
Apr 29, 2017 at 4:34
• @yode, I've taken it into consideration now ))) Apr 29, 2017 at 4:57