1

I wanted to build a function that finds all the possible subsets of a set. The first function works well, while the second doesn't. In the first I used a list comprehension to remove the first element of a list, while in the second I used pop(0). Why do they output different results? The first function is:

def combinations(n):
   if len(n) == 1:
       return [[], n]
   a = [element for element in n if element != n[0]]
   return [[n[0]] + comb for comb in combinations(a)] + combinations(a)

The second function is:

def combinations(n):
   if len(n) == 1:
       return [[], n]
   a = n
   a.pop(0)
   return [[n[0]] + comb for comb in combinations(a)] + combinations(a)

The output of the first is:

[[0, 1, 2], [0, 1, 2, 3], [0, 1], [0, 1, 3], [0, 2], [0, 2, 3], [0], [0, 3], [1, 2], [1, 2, 3], [1], [1, 3], [2], [2, 3], [], [3]]

The output of the second is:

[[3, 3, 3], [3, 3, 3, 3], [3, 3], [3, 3, 3], [3], [3, 3], [], [3]]
Muhteva
  • 2,729
  • 2
  • 9
  • 21
Glacialyx
  • 11
  • 3
  • 4
    Note that `a = n` doesn't make a copy. Those are two names for the same list. The list comprehension in the first code does produce a filtered copy of `n` though. – Carcigenicate Aug 10 '21 at 15:22
  • Thanks for the answer. So basically, i'm just referring to the same list, but with a different name? – Glacialyx Aug 10 '21 at 15:25
  • Yes. Python doesn't make copies for you on assignment. [This](https://stackoverflow.com/questions/2438938/does-python-make-a-copy-of-objects-on-assignment) would be a good read-over. `a = n` just creates a second label, `a`, that points to the same list as `n`. You can see that with `print(id(a), id(n))`. They point to the same memory location. – Carcigenicate Aug 10 '21 at 15:26

1 Answers1

1

Already answered in the comments. In addition, this should solve the problem.

def combinations(n):
   if len(n) == 1:
       return [[], n]
   a = list(n)
   a.pop(0)
   return [[n[0]] + comb for comb in combinations(a)] + combinations(a)
Muhteva
  • 2,729
  • 2
  • 9
  • 21