2

I am trying to create a dictionary(sums), whose keys are the total sum of a list and value is the list itself. This list has a varying number of elements but the same name. Each time the elements of the list are changed and this changed list(same name) is assigned to a different key, the previously assigned value to key also changes.

While looking for some suitable answer to this, I learned from here(https://stackoverflow.com/a/52806573/7198441) that this could be because Python also references lists(Please correct me if am making an error here). Now, I want to know, if there is a way that I can assign a list having the same name but different elements at different stages of iteration to different keys of the same dictionary.

l = [1, 2, 3, 4, 5]

sums = {}

while len(l) :

    l_sum = sum(l)
    sums[l_sum] = l

    print(sums)
    print()

    l.pop()

Actual result:

{15: [1, 2, 3, 4, 5]}

{15: [1, 2, 3, 4], 10: [1, 2, 3, 4]}

{15: [1, 2, 3], 10: [1, 2, 3], 6: [1, 2, 3]}

{15: [1, 2], 10: [1, 2], 6: [1, 2], 3: [1, 2]}

{15: [1], 10: [1], 6: [1], 3: [1], 1: [1]}

Expected:

{15: [1, 2, 3, 4, 5]}

{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4]}

{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3]}

{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2]}

{15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2], 1: [1]}
Mazdak
  • 105,000
  • 18
  • 159
  • 188
AbhisheK
  • 33
  • 5

2 Answers2

1

You're doing all the operation on one instance of your list object. That's why in the final result you get the same list for all the values. Instead of a loop, as a more Pythonic way you can use a dictionary comprehension or itertools.accumulate to get the accumulative sum of the list items and then use zip to create your expected dictionary.

In [13]: {sum(l[:i + 1]): l[:i + 1] for i in range(len(l))}
Out[13]: {1: [1], 3: [1, 2], 6: [1, 2, 3], 10: [1, 2, 3, 4], 15: [1, 2, 3, 4, 5]}

Or (less Pythonic):

In [7]: dict(zip(accumulate(l), [l[:i + 1] for i in range(len(l))]))
Out[7]: {1: [1], 3: [1, 2], 6: [1, 2, 3], 10: [1, 2, 3, 4], 15: [1, 2, 3, 4, 5]}
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • I appreciate the quality of answer @Kasrâmvd, but I was looking for a solution like the one I've accepted. Thanks! – AbhisheK May 22 '19 at 16:53
1

The problem is that when you do sums[l_sum] = l, you are working with the reference to the original list. So, all the changes during any step of the while loop will affect all the other places where this list has been used. That's why you see that in each print, your list changes.

The simple solution is to use sums[l_sum] = l[:] to copy the list.


while len(l) :
    l_sum = sum(l)
    sums[l_sum] = l[:] # <--- changed here from l to l[:]
    print(sums)
    print()
    l.pop()

# {15: [1, 2, 3, 4, 5]}

# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4]}

# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3]}

# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2]}

# {15: [1, 2, 3, 4, 5], 10: [1, 2, 3, 4], 6: [1, 2, 3], 3: [1, 2], 1: [1]}
Sheldore
  • 37,862
  • 7
  • 57
  • 71