I need to write a function add_to_dict(d, key_value_pairs)
which adds each given key/value pair to a python dictionary. The argument key_value_pairs
will be a list of tuples in the form (key, value)
.
The function should return a list of all of the key/value pairs which have changed (with their original values).
def add_to_dict(d, key_value_pairs):
newlist = []
for key,value in d:
for x,y in key_value_pairs:
if x == key:
newlist.append(x,y)
return newlist
I keep getting an error
ValueError: not enough values to unpack (expected 2, got 1)
How do I solve this error?
The “ValueError: not enough values to unpack” error is raised when you try to unpack more values from an iterable object than those that exist. To fix this error, make sure the number of values you unpack from an iterable is equal to the number of values in that iterable.
The Python "ValueError: too many values to unpack (expected 2) in Python" occurs when the number of variables in the assignment is not the same as the number of values in the iterable. To solve the error, declare exactly as many variables as there are items in the iterable.
This error occurs when the number of variables doesn't match the number of values. As a result of the inequality, Python doesn't know which values to assign to which variables, causing us to get the error ValueError: too many values to unpack .
'''
@param d: a dictionary
@param key_value_pairs: a list of tuples in the form `(key, value)`
@return: a list of tuples of key-value-pair updated in the original dictionary
'''
def add_to_dict(d, key_value_pairs):
newlist = []
for pair in key_value_pairs:
# As is mentioned by Mr Patrick
# you might not want to unpack the key-value-pair instantly
# to avoid possible corrupted data input from
# argument `key_value_pairs`
# if you can't guarantee its integrity
try:
x, y = pair
except (ValueError):
# unable to unpack tuple
tuple_length = len(pair)
raise RuntimeError('''Invalid argument `key_value_pairs`!
Corrupted key-value-pair has ({}) length!'''.format(tuple_length))
# Instead of using nesting loop
# using API would be much more preferable
v = d.get(x)
# Check if the key is already in the dictionary `d`
if v:
# You probably mean to append a tuple
# as `array.append(x)` takes only one argument
# @see: https://docs.python.org/3.7/library/array.html#array.array.append
#
# Besides, hereby I quote
# "The function should return a list of all of the key/value pairs which have changed (with their original values)."
# Thus instead of using the following line:
#
# newlist.append((x, y,))
#
# You might want a tuple of (key, old_value, new_value)
# Hence:
newlist.append((x, v, y,))
# I don't know if you want to update the key-value-pair in the dictionary `d`
# take out the following line if you don't want it
d[x] = y
return newlist
Please keep reading the remaining part if you want to know how to traverse a dict
object properly.
dict
objectThe following segments demonstrate how to traverse a dict
in Python 3.x.
for key in d:
value = d[key]
print(key, value)
the code segment above has the same effect as the following one:
for key in d.keys():
value = d[key]
print(key, value)
for key, value in d.items():
print(key, value)
for value in d.values():
print(value)
The following segments demonstrate how to traverse a dict
in Python 2.x.
for key in d:
value = d[key]
print(key, value)
keys()
returns a list of the key set of dictionary d
for key in d.keys():
value = d[key]
print(key, value)
iterkeys()
returns an iterator of the key set of dictionary d
for key in d.iterkeys():
value = d[key]
print(key, value)
values()
returns a list of the key-value-pair set of dictionary d
for key, value in d.items():
print(key, value)
itervalues()
returns an iterator of the key-value-pair set of dictionary d
for key, value in d.iteritems():
print(key, value)
values()
returns a list of the value set of dictionary d
for value in d.values():
print(value)
itervalues()
returns a iterator of the value set of dictionary d
for value in d.itervalues():
print(value)
Reference:
use items()
to resolve, like:
d = {"foo": "bar"}
for key, value in d.items():
print key, value
You can avoid this error if you do not iterate over the dict (of 1 million entries) but only over the list of possible changes and see if it changes anything in the dict:
def add_to_dict(d, key_value_pairs):
"""Adds all tuples from key_value_pairs as key:value to dict d,
returns list of tuples of keys that got changed as (key, old value)"""
newlist = []
for item in key_value_pairs:
# this handles your possible unpacking errors
# if your list contains bad data
try:
key, value = item
except (TypeError,ValueError):
print("Unable to unpack {} into key,value".format(item))
# create entry into dict if needed, else gets existing
entry = d.setdefault(key,value)
# if we created it or it is unchanged this won't execute
if entry != value:
# add to list
newlist.append( (key, entry) )
# change value
d[key] = value
return newlist
d = {}
print(add_to_dict(d, ( (1,4), (2,5) ) )) # ok, no change
print(add_to_dict(d, ( (1,4), (2,5), 3 ) )) # not ok, no changes
print(add_to_dict(d, ( (1,7), (2,5), 3 ) )) # not ok, 1 change
Output:
[] # ok
Unable to unpack 3 into key,value
[] # not ok, no change
Unable to unpack 3 into key,value
[(1, 4)] # not ok, 1 change
You could also throw in some validation onto your parameters - if any parameter is wrong, nothing will be executed and an speaking error arises:
import collections
def add_to_dict(d, key_value_pairs):
"""Adds all tuples from key_value_pairs as key:value to dict d,
returns list of tuples of keys that got changed as (key, old value)"""
if not isinstance(d,dict):
raise ValueError("The dictionary input to add_to_dict(dictionary,list of tuples)) is no dict")
if not isinstance(key_value_pairs,collections.Iterable):
raise ValueError("The list of tuples input to add_to_dict(dictionary,list of tuples)) is no list")
if len(key_value_pairs) > 0:
if any(not isinstance(k,tuple) for k in key_value_pairs):
raise ValueError("The list of tuples includes 'non tuple' inputs")
if any(len(k) != 2 for k in key_value_pairs):
raise ValueError("The list of tuples includes 'tuple' != 2 elements")
newlist = []
for item in key_value_pairs:
key, value = item
# create entry into dict if needed, else gets existing
entry = d.setdefault(key,value)
# if we created it or it is unchanged this won't execute
if entry != value:
# add to list
newlist.append( (key, entry) )
# change value
d[key] = value
return newlist
So you get clearer error messages:
add_to_dict({},"tata")
# The list of tuples input to add_to_dict(dictionary,list of tuples)) is no list
add_to_dict({},["tata"])
# The list of tuples includes 'non tuple' inputs
add_to_dict({},[ (1,2,3) ])
# The list of tuples includes 'tuple' != 2 elements
add_to_dict({},[ (1,2) ])
# ok
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With