2

I would like to have a function split_list([1,2,4,3]) which yields the following 7 lists:

[[1], [2,4,3]]
[[1,2], [4,3]]
[[1,2,4], [3]]
[[1,2], [4],[3]]
[[1],[2,4],[3]]
[[1],[2],[4,3]]
[[1],[2],[4],[3]]

where the smaller lists are yielded first - [[1], [2,4,3]] has length 2 while [[1],[2],[4],[3]] is yielded last because its length is 4. This is as far as I have gotten with it:

def split_list(l):
  for i in range(1, len(l)):
    yield [l[:i],l[i:]]

for i in split_list((1,2,4,3)):
    print(i)
Baz
  • 12,713
  • 38
  • 145
  • 268
  • What do you mean by smaller lists? – HakunaMaData Dec 28 '18 at 21:37
  • @RobS The length of [[1], [2,4,3]] is 2 while the length of [[1],[2],[4],[3]] is 4. – Baz Dec 28 '18 at 21:40
  • maybe dupe: [How to find all partitions of a list S into k subsets (can be empty)?](https://stackoverflow.com/q/53937159/674039) – wim Dec 28 '18 at 21:41
  • or: [How to split a list into n groups in all possible combinations of group length and elements within group?](https://stackoverflow.com/q/39192777/674039) – wim Dec 28 '18 at 21:42
  • or: [Show all possible groupings of a list, given only the amount of sublists (lengths are variable)](https://stackoverflow.com/q/9088321/674039) – wim Dec 28 '18 at 21:43
  • Possible duplicate of [How to split a list into n groups in all possible combinations of group length and elements within group?](https://stackoverflow.com/questions/39192777/how-to-split-a-list-into-n-groups-in-all-possible-combinations-of-group-length-a) – James Dec 28 '18 at 21:46
  • Do you want the sub-lists in that specific order? – Dani Mesejo Dec 28 '18 at 21:50
  • @Daniel Mesejo No, as long as the lists yielded get larger – Baz Dec 28 '18 at 21:54
  • 1
    Do you want to exclude the main list as the first element? For example [[1, 2, 3, 4]] – Dani Mesejo Dec 28 '18 at 22:02

3 Answers3

1

You can utilize list slicing with recursion:

def split_list(d):
   for i in range(len(d)):
      if len(d[i+1:]) > 0:
        for c in split_list(d[i+1:]):
          yield [d[:i+1], *c]
      else:
        yield [d]

print(list(split_list([1,2,4,3])))

Output:

[[[1], [2], [4], [3]], [[1], [2], [4, 3]], [[1], [2, 4], [3]], [[1], [2, 4, 3]], [[1, 2], [4], [3]], [[1, 2], [4, 3]], [[1, 2, 4], [3]], [[1, 2, 4, 3]]]

Edit: event shorter

def split_list(d):
  if len(d) > 1:
    return [list(filter(None, [d[:i+1], *c])) for i in range(len(d)) for c in split_list(d[i+1:])]
  return [d] if not isinstance(d, list) else [[d]]

Output:

[[[1], [2], [4], [3]], [[1], [2], [4, 3]], [[1], [2, 4], [3]], [[1], [2, 4, 3]], [[1, 2], [4], [3]], [[1, 2], [4, 3]], [[1, 2, 4], [3]], [[1, 2, 4, 3]]]
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
1

If including the list itself as the first element is not a problem, you could so something like this:

def split_list(lst):
    if not lst:
        yield []

    for i in range(len(lst), 0, -1):
        for j in split_list(lst[i:]):
            yield [lst[:i]] + j


for l in split_list([1, 2, 4, 3]):
    print(l)

Output

[[1, 2, 4, 3]]
[[1, 2, 4], [3]]
[[1, 2], [4, 3]]
[[1, 2], [4], [3]]
[[1], [2, 4, 3]]
[[1], [2, 4], [3]]
[[1], [2], [4, 3]]
[[1], [2], [4], [3]]
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
1

Try this one:

def split_list(l):
    if len(l) == 1:
        yield [ l ]
        return

    for s in split_list(l[1:]):
        for n, sub in enumerate(s):
            if len((s[:n] + [[ l[0] ] + sub]  + s[n+1:])[0]) !=4:
                yield s[:n] + [[ l[0] ] + sub]  + s[n+1:]           
        yield [[l[0]]] + s

for lst in split_list([1, 2, 3, 4]):
        print lst

The problem is solved recursively. And in output:

[[1], [2, 3, 4]]
[[1, 2], [3, 4]]
[[2], [1, 3, 4]]
[[1], [2], [3, 4]]
[[1, 2, 3], [4]]
[[2, 3], [1, 4]]
[[1], [2, 3], [4]]
[[1, 3], [2, 4]]
[[3], [1, 2, 4]]
[[1], [3], [2, 4]]
[[1, 2], [3], [4]]
[[2], [1, 3], [4]]
[[2], [3], [1, 4]]
[[1], [2], [3], [4]]
Kian
  • 1,319
  • 1
  • 13
  • 23