Update the first value of a dictionary - python

I have a list of multiple dictionaries.
The structure of my dictionaries are like that :
{'word': 'hello world', 'definition': 'saying hello to the world'}
I would like to update only the first value, so here 'hello world' in order to have it in upper case.
Here is my comprehension list i'm trying with:
upper = {key: value.upper()[0] for key, value in words_dict.items()}
The problem is that with this I have this result:
{'word': 'H', 'definition': 'S'}
I've tried loads of things but I'm still blocked...

A list comprehension is not very useful if all you want is to change the first item of the dict. You can change the dict in-place.
One way of doing it, without specifying the key name:
words_dict[next(iter(words_dict))] = words_dict[next(iter(words_dict))].upper()

You could do something like
upper = {key: words_dict[key].upper() if idx==0 else words_dict[key] for idx, key in enumerate(words_dict.keys())}
But using a dictionary comprehension here is hardly very readable. Perhaps a more readable approach would be to copy the dictionary and then just modify the first element.
upper = words_dict.copy()
first = list(upper.keys())[0]
upper[first] = upper[first].upper()
If you want to update the original dictionary, obviously operate on the original instead of on a copy.

Related

Update Python dictionary while looping

I was trying to iterate over a list of values, craft a dictionary to save each value in a structured way, and then append the dictionary to a new list of results, but I found an unexpected behavior.
Below is an example:
values_list = [1,2,3]
# Basic dict
result_dict = {
'my_value': ''
}
# Iterate, craft a dictionary, and append result
dicts_list = []
for value in values_list:
result_dict.update({'my_value': value})
dicts_list.append(result_dict)
print(dicts_list)
As you can see, first I create a basic dictionary, then I'm iterating over the list of values and updating the dictionary, at the end I'm appending the crafted dictionary to a separate list of results (dicts_list).
As a result I was expecting:
[{'my_value': 1}, {'my_value': 2}, {'my_value': 3}]
but instead I was getting:
[{'my_value': 3}, {'my_value': 3}, {'my_value': 3}]
It looks like every iteration is not only updating the basic dictionary – which is expected – but also the dictionaries already appended to the list of results on the previous iteration.
To fix the issue, I nested the basic dictionary under the for loop:
values_list = [1,2,3]
# Iterate, craft a dictionary, and append result
dicts_list = []
for value in values_list:
result_dict = {'my_value': ''}
result_dict.update({'my_value': value})
dicts_list.append(result_dict)
print(dicts_list)
Can anyone explain what is wrong with the first approach? How is the loop causing the list of appended dictionaries to be updated?
Thanks for any advice! :)
Franz
As explained in the comment, you're appending the same dictionary in each iteration because update() modifies the result_dict rather than returning a copy. So, the only change you need to do is to append a copy of the crafted dictionary. For example:
values_list = [1,2,3]
# Basic dict
result_dict = {
'my_value': ''
}
# Iterate, craft a dictionary, and append result
dicts_list = []
for value in values_list:
result_dict.update({'my_value': value})
dicts_list.append(dict(result_dict)) # <--- this is the only change
print(dicts_list)
To gain understanding of How is the loop causing the list of appended dictionaries to be updated? you can use Python Tutor: Visualize code in Python with the code you provided in your question to see the effect of executing the code line by line with the final result being following visualization:
I suggest you read also Facts and myths about Python names and values.

Check for string in list items using list as reference

I want to replace items in a list based on another list as reference.
Take this example lists stored inside a dictionary:
dict1 = {
"artist1": ["dance pop","pop","funky pop"],
"artist2": ["chill house","electro house"],
"artist3": ["dark techno","electro techno"]
}
Then, I have this list as reference:
wish_list = ["house","pop","techno"]
My result should look like this:
dict1 = {
"artist1": ["pop"],
"artist2": ["house"],
"artist3": ["techno"]
}
I want to check if any of the list items inside "wishlist" is inside one of the values of the dict1. I tried around with regex, any.
This was an approach with just 1 list instead of a dictionary of multiple lists:
check = any(item in artist for item in wish_list)
if check == True:
artist_genres.clear()
artist_genres.append()
I am just beginning with Python on my own and am playing around with the SpotifyAPI to clean up my favorite songs into playlists. Thank you very much for your help!
The idea is like this,
dict1 = { "artist1" : ["dance pop","pop","funky pop"],
"artist2" : ["house","electro house"],
"artist3" : ["techno","electro techno"] }
wish_list = ["house","pop","techno"]
dict2={}
for key,value in dict1.items():
for i in wish_list:
if i in value:
dict2[key]=i
break
print(dict2)
A regex is not needed, you can get away by simply iterating over the list:
wish_list = ["house","pop","techno"]
dict1 = {
"artist1": ["dance pop","pop","funky pop"],
"artist2": ["chill house","electro house"],
"artist3": ["dark techno","electro techno"]
}
dict1 = {
# The key is reused as-is, no need to change it.
# The new value is the wishlist, filtered based on its presence in the current value
key: [genre for genre in wish_list if any(genre in item for item in value)]
for key, value in dict1.items() # this method returns a tuple (key, value) for each entry in the dictionary
}
This implementation relies a lot on list comprehensions (and also dictionary comprehensions), you might want to check it if it's new to you.

How do I turn list values into an array with an index that matches the other dic values?

Hoping someone can help me out. I've spent the past couple hours trying to solve this, and fair warning, I'm still fairly new to python.
This is a repost of a question I recently deleted. I've misinterpreted my code in the last example.The correct example is:
I have a dictionary, with a list that looks similar to:
dic = [
{
'name': 'john',
'items': ['pants_1', 'shirt_2','socks_3']
},
{
'name': 'bob',
items: ['jacket_1', 'hat_1']
}
]
I'm using .append for both 'name', and 'items', which adds the dic values into two new lists:
for x in dic:
dic_name.append(dic['name'])
dic_items.append(dic['items'])
I need to split the item value using '_' as the delimiter, so I've also split the values by doing:
name, items = [i if i is None else i.split('_')[0] for i in dic_name],
[if i is None else i.split('_')[0] for i in chain(*dic_items)])
None is used in case there is no value. This provides me with a new list for name, items, with the delimiter used. Disregard the fact that I used '_' split for names in this example.
When I use this, the index for name, and item no longer match. Do i need to create the listed items in an array to match the name index, and if so, how?
Ideally, I want name[0] (which is john), to also match items[0] (as an array of the items in the list, so pants, shirt, socks). This way when I refer to index 0 for name, it also grabs all the values for items as index 0. The same thing regarding the index used for bob [1], which should match his items with the same index.
#avinash-raj, thanks for your patience, as I've had to update my question to reflect more closely to the code I'm working with.
I'm reading a little bit between the lines but are you trying to just collapse the list and get rid of the field names, e.g.:
>>> dic = [{'name': 'john', 'items':['pants_1','shirt_2','socks_3']},
{'name': 'bob', 'items':['jacket_1','hat_1']}]
>>> data = {d['name']: dict(i.split('_') for i in d['items']) for d in dic}
>>> data
{'bob': {'hat': '1', 'jacket': '1'},
'john': {'pants': '1', 'shirt': '2', 'socks': '3'}}
Now the data is directly related vs. indirectly related via a common index into 2 lists. If you want the dictionary split out you can always
>>> dic_name, dic_items = zip(*data.items())
>>> dic_name
('bob', 'john')
>>> dic_items
({'hat': '1', 'jacket': '1'}, {'pants': '1', 'shirt': '2', 'socks': '3'})
You need a list of dictionaries because the duplicate keys name and items are overwritten:
items = [[i.split('_')[0] for i in d['items']] for d in your_list]
names = [d['name'] for d in your_list] # then grab names from list
Alternatively, you can do this in one line with the built-in zip method and generators, like so:
names, items = zip(*((i['name'], [j.split('_')[0] for j in i['items']]) for i in dic))
From Looping Techniques in the Tutorial.
for name, items in div.items():
names.append(name)
items.append(item)
That will work if your dict is structured
{'name':[item1]}
In the loop body of
for x in dic:
dic_name.append(dic['name'])
dic_items.append(dic['items'])
you'll probably want to access x (to which the items in dic will be assigned in turn) rather than dic.

Sorting list of dictionaries according to a certain key

runnerList = [{1:{"name":"John","height":173,"age":16}},
{2:{"name":"Fred","height":185,"age":18}},
{3:{"name":"Luke","height":181,"age":17}}]
I've been trying to sort this list of dictionaries in ascending order according to the age of the runners, with no success :( I tried:
import operator
runnerList.sort(key=lambda x: x['age'], reverse=True)
But nothing seemed to happen. How would i do this?
Try this:
runnerList.sort(key=lambda x: x.values()[0]['age'])
print runnerList
The reason you were getting an error is that your relevant dictionaries (those containing the age key) were also contained inside another dictionary. The solution was just as simple getting the values() of that external dict and getting grabbing the first element ([0]) which gave you the only dictionary contained inside.
Also, I removed the reverse=True used in your example. It would have given you the results in descending order and you specifically asked for them to be in ascending order.
Disclaimer:
If you're using a Python version >= 3:, you'd have to convert the generator object created with values().
runnerList.sort(key=lambda x: list(x.values())[0]['age'])
runnerList is list of dictionaries of dictionaries.
if you are sure that each list entry has only one pair of key-value, then you can sort by:
runnerList.sort(key=lambda x: list(x.values())[0]['age'], reverse=True)
if each list entry has more then one key-value pair, then you need to specify better the logic of your sort. what would you do on list like this?:
runnerList = [{1:{"name":"John","height":173,"age":16}},
{ 2:{"name":"Fred","height":185,"age":18},
4:{"name":"Fred","height":185,"age":13}
},
{3:{"name":"Luke","height":181,"age":17}}]
You basically have the runnerList in form of list as it is enclosed in []. First change it to dictionary like
runnerList = {1:{"name":"John","height":173,"age":16},
2:{"name":"Fred","height":185,"age":18},
3:{"name":"Luke","height":181,"age":17} }
and then you can import operator and can use the below function to sort the items and print it
sorted_runnerList = sorted(runnerList.items(),key=lambda x: x[1]['age'],)
While this would directly sort the age in the dictionary within the dictionary
So basically your function becomes
import operator
runnerList = {1:{"name":"John","height":173,"age":16},
2:{"name":"Fred","height":185,"age":18},
3:{"name":"Luke","height":181,"age":17} }
sorted_runnerList = sorted(runnerList.items(),key=lambda x: x[1]['age'],)
print sorted_runnerList
But do remember as we are using the .items() it would return immutable tuples
Output
[(1, {'age': 16, 'name': 'John', 'height': 173}), (3, {'age': 17, 'name': 'Luke', 'height': 181}), (2, {'age': 18, 'name
': 'Fred', 'height': 185})]

Python Dictionary - List Nesting

I have a dictionary with a key and a pair of values, the values are stored in a List. But i'm keeping the list empty so i can .append its values ,i cant seem to be able to do this
>>>myDict = {'Numbers':[]}
>>>myDict['Numbers'[1].append(user_inputs)
doesn't seem to work, returns an error . How do i refer to the list in myDict so i can append its values.
Also is it possible to have a dictionary inside a list and also have another list inside? if so? what is its syntax or can you recommend anyother way i can do this
>>>myDict2 = {'Names': [{'first name':[],'Second name':[]}]}
do i change the second nested list to a tuple?? Please lets keep it to PYTHON 2.7
You get an error because your syntax is wrong. The following appends to the list value for the 'Numbers' key:
myDict['Numbers'].append(user_inputs)
You can nest Python objects arbitrarily; your myDict2 syntax is entirely correct. Only the keys need to be immutable (so a tuple vs. a list), but your keys are all strings:
>>> myDict2 = {'Names': [{'first name':[],'Second name':[]}]}
>>> myDict2['Names']
[{'first name': [], 'Second name': []}]
>>> myDict2['Names'][0]
{'first name': [], 'Second name': []}
>>> myDict2['Names'][0]['first name']
[]
You should access the list with myDict['Numbers']:
>>>myDict['Numbers'].append(user_inputs)
You can have dicts inside of a list.
The only catch is that dictionary keys have to be immutable, so you can't have dicts or lists as keys.
You may want to look into the json library, which supports a mix of nested dictionaries and lists.
In addition, you may also be interested in the setdefault method of the dictionary class.
Format is something like:
new_dict = dict()
some_list = ['1', '2', '3', ...]
for idx, val in enumerate(some_list):
something = get_something(idx)
new_dict.setdefault(val, []).append(something)

Categories

Resources