0

Here is a problem I had to do:

We are going to implement a very helpful function, called group.

group takes a list of things and returns a list of group, where each group is formed by all equal consecutive elements in the list.

For example:

group([1, 1, 1, 2, 3, 1, 1]) == [[1, 1, 1], [2], [3], [1, 1]]

group([1, 2, 1, 2, 3, 3]) == [[1], [2], [1], [2], [3, 3]]

And here is my initial solution:

def group(int_list):    

group_list = []
current_list = []

for i in range(len(int_list)):
    if int_list[i] not in current_list:
        if len(current_list) != 0:
            group_list.append(current_list)
        del current_list[:]
        current_list.append(int_list[i])
    else:
        current_list.append(int_list[i])    

group_list.append(current_list)

return group_list

And the output I was getting:

[[1, 1], [1, 1], [1, 1], [1, 1]]

After spending like 30 minutes trying to figure out the problem, I changed the 9th line from group_list.append(current_list) to group_list.append(current_list[:]) and surprisingly the magic worked. I got the correct output:

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

So I guess my question is what's the difference between current_list and current_list[:] ?

Boyan Kushlev
  • 1,043
  • 1
  • 18
  • 35
  • Another way to fix the original code is to change `del current_list[:]` to `current_list = []`, this way the next time you append `current_list` it's going to be a different list (i.e. no need to make a shallow copy). – gatto Dec 06 '15 at 13:27

2 Answers2

2

current_list[:] is a shallow copy of current_list; e.g.,:

In your function, you're building up a list (of the current group) in the thing referred to by current_list. When you're done, you add this thing to group_list, and then reset the thing by deleting all of its contents (del current_list[:]). We have to remember that everything in Python is a reference, so, using your first code, group_list contains several references to the same object (this is why your output looks like [[1, 1], [1, 1], [1, 1], [1, 1]]). When you delete the contents of current_list and add new elements later on, you do this to every element of group_list, too.

Using the current_list[:] syntax that you discovered, you create a copy of current_list and add this onto group_list; this copy is not modified later when you delete the contents of current_list.

Community
  • 1
  • 1
wildwilhelm
  • 4,809
  • 1
  • 19
  • 24
  • So is this the correct way to do it? Just by adding [:] – Boyan Kushlev Dec 06 '15 at 13:47
  • 1
    @BobbyBrown it seems the consensus is that, in terms of code style, it's clearer to create shallow copies by writing `list(current_list)` than `current_list[:]`. This is just aesthetics, though; creating copies with the slice operator works fine. – wildwilhelm Dec 06 '15 at 13:55
1

Basicaly the main difference is that current_list is the reference to the list, and current_list[:] is a new array with the elements of the list. So, using the first one, when you change current_list, group_list is also changed. The other way if you change current_list, group_list is not modified.

Hoter
  • 155
  • 1
  • 7