-1

I've run into an issue that I've most likely solved before but forgot how I did.

I want to have a dict be able to take as many values as you throw at it, in my case, 4 values, and not have a predetermined limit of values it expects to unpack.

The example input I'm trying to run is:

2

USA Boston Pittsburgh Washington Seattle

UK London Edinburgh Cardiff Belfast

This is a small debug build of the program. You input an int and you input that many keys and their respective one value:

cNamesandCountries = dict()
n = int(input())
for i in range(n):
  user_input = input()
  key, value = user_input.split()
  cNamesandCountries[key] = value
print(cNamesandCountries)

I attempted to fix the problem by doing this:

cNamesandCountries = dict()
n = int(input())
for i in range(n):
  user_input = input()
  key, value, value, value, value = user_input.split()
  cNamesandCountries[key] = value, value, value, value
print(cNamesandCountries)

but the output I received was this:

{'USA': ('Seattle', 'Seattle', 'Seattle', 'Seattle'), 'UK': ('Belfast', 'Belfast', 'Belfast', 'Belfast')}

Of course, that isn't supposed to be happening. It's taking the last value of my input and using it for every value in my dict. I want the output to be this:

{'USA': ('Boston', 'Pittsburgh', 'Washington', 'Seattle'), 'UK': ('London', 'Edinburgh', 'Cardiff', 'Belfast')}

I know that I can solve this issue by having the dict take in however many values are inputted into the code, but I don't know how I would get it to do that.

Pika Supports Ukraine
  • 3,612
  • 10
  • 26
  • 42

1 Answers1

0

The problem is in reusing the same value variable in the left hand side of the assignment:

key, value, value, value, value = user_input.split()

The value is got reassigned and you get only the last one.

Do this instead:

cNamesandCountries = dict()
n = int(input())
for i in range(n):
  user_input = input()
  split_input = user_input.split()
  cNamesandCountries[split_input[0]] = split_input[1:]
print(cNamesandCountries)

Let's see first why the initial code does not work. The assignment where on the left hand side is the list of variables and on the right hand side there's a sequence (lists and tuples are examples of sequences) is sometimes referred to as sequence unpacking.

It works like this. Consider the example:

a, b = (1+2, 2+3)

The right hand side is evaluated first and we get a tuple (3, 5) and then each element starting from the first is assigned to the corresponding variable on the left hand side.

It is allowed (though not very useful) to specify the same variable multiple times:

a, a = (2, 3)

In the above case a would be assigned 2 and immediately after that a would be assigned 3.

Let's get back to the original example:

key, value, value, value, value = user_input.split()

On the right hand side there's a call to string's split function which takes a string and produces a list of strings:

>>> "USA Boston Pittsburgh Washington Seattle".split()
['USA', 'Boston', 'Pittsburgh', 'Washington', 'Seattle']

The first element of the resulting list is assigned to key variable. Then all other elements are assigned to value variable in turn starting with Boston and finishing with Seattle. Note that each assignment overwrites the previous value of the value variable. So the end result is that value is equal to Seattle.

Then the next operation creates a tuple of four elements each having value Seattle:

('Seatle', 'Seatle', 'Seatle', 'Seatle')

and puts it into the cNamesandCountries dictionary with the key equal to the value of key variable namely 'USA'.

The working example does not use sequence unpacking. It assigns the result of the split (which is the list) to the split_input variable. Then it uses its first element (which is USA) as a key and all elements but the first as a value.

The expression split_input[1:] is a slice of the list that is the result of this operation is a new list that consists of the values that are stored in the split_input list starting from the index 1 and up to the end of the list:

>>> split_input="USA Boston Pittsburgh Washington Seattle".split()
>>> split_input[0]
'USA'
>>> split_input[1:]
['Boston', 'Pittsburgh', 'Washington', 'Seattle']

Note that lists (and tuples) have zero based indices.