Subsets of a list

I would use:

data = {1, 20, 3, 40};

Join @@ Permutations /@ IntegerPartitions[Length@data];

results = Internal`PartitionRagged[data, #] & /@ %
{{4}, {3, 1}, {1, 3}, {2, 2}, {2, 1, 1}, {1, 2, 1}, {1, 1, 2}, {1, 1, 1, 1}}

{{{1, 20, 3, 40}},
 {{1, 20, 3}, {40}},
 {{1}, {20, 3, 40}},
 {{1, 20}, {3, 40}},
 {{1, 20}, {3}, {40}},
 {{1}, {20, 3}, {40}},
 {{1}, {20}, {3, 40}},
 {{1}, {20}, {3}, {40}}}

IntegerPartitions is used get the ways in which you can split a list, to be used with the function above. Permutations is used to get all orders of these. By the way, you could use the function Compositions from the Combinatorica package in place of both of these if you want to include zeros.

These specifications are fed to Internal`PartitionRagged which splits a list into given lengths, e.g. [{1,2,3,4,5}, {2,1,2}] -> {{1,2}, {3}, {4,5}}. Users of Mathematica versions prior to 8 can use my dynamicPartition function in its place.


You might generate all subsets by placing special markers (asterisks) where a list should be split.

data = {1, 20, 3, 40};

(* The asterisks "*" indicate where a list should be split *)
data1 = Insert[data, "*", #] & /@ (Subsets[Range[2, Length[data]]] /.  a_Integer :>  {a})

(* out *)   
{{1, 20, 3, 40}, {1, "*", 20, 3, 40}, {1, 20, "*", 3, 40}, {1, 20, 3, "*", 40}, 
 {1, "*", 20, "*", 3, 40}, {1, "*", 20, 3, "*", 40}, {1,  20, "*", 3, "*", 40}, 
 {1, "*", 20, "*", 3, "*", 40}}

(*  s actually does the splitting  *)
s[list_] := Split[list, # =!= "*" &]

(* t removes asterisks *)
t[list_] := DeleteCases[#, "*"] & /@ list

t[#] & /@ (s[#] & /@ data1)

(* out *)
{{{1, 20, 3, 40}}, {{1}, {20, 3, 40}}, {{1, 20}, {3, 40}}, {{1, 20, 3}, {40}}, 
 {{1}, {20}, {3, 40}}, {{1}, {20, 3}, {40}}, 
 {{1, 20}, {3}, {40}}, {{1}, {20}, {3}, {40}}}

Note

The following snippet targeted all the positions in data where splits could be made:

Subsets[Range[2, Length[data]]] 
(*  out *)

{{}, {2}, {3}, {4}, {2, 3}, {2, 4}, {3, 4}, {2, 3, 4}}

So the first list had no splits; the second list was split at position 2, that is, after the first element; the third list was split at position 3; ... and the final list was split at positions 2, 3 and 4.


data = {1, 20, 3, 40};
i = Join @@ Permutations /@ IntegerPartitions[Length[data]];

In version 11.2 TakeList is introduced which does the same thing as Internal'PartitionRagged plus more. But even though TakeList has more functionality, it evaluates much faster:

Do[Internal`PartitionRagged[data, #] & /@ i, {1000}] // RepeatedTiming
Do[                TakeList[data, #] & /@ i, {1000}] // RepeatedTiming

{0.337, Null}
{0.0210, Null}