Reputation: 1040
I have a nested list that looks like this:
my_list = [['Raji GlovesSixSixOneRegular price',
'Sale price$9.95',
' Save 67%'],
['Comp Vortex GlovesSixSixOneRegular price',
'Sale price$9.95',
' Save 67%'],
["Shasta 3/4 Cycling Tights - Women'sSpecializedRegular price",
'Sale price$14.95',
' Save 79%']]
I would like to create a nested dictionary such that, the first value in each list item is the 'ItemName', the second is the 'SalePrice' and the third is the 'Saving'. such like this:
dict = {1: {'ItemName': 'Comp Vortex GlovesSixSixOneRegular price',
'SalePrice': 'Sale price$9.95',
'Saving': ' Save 79%'},
2: {'ItemName': 'Raji GlovesSixSixOneRegular price',
'SalePrice': 'Sale price$9.95',
'Saving': ' Save 79%'},
3: {'ItemName': 'Shasta 3/4 Cycling Tights - WomensSpecializedRegular price',
'SalePrice': 'Sale price$14.95',
'Saving': ' Save 79%'}}
keys = ('ItemName', 'SalePrice','Saving')
I know I could do something like this, if I was just adding the first item in the list:
values= my_list[0]
values
res = {}
for key in keys:
for value in values:
res[key] = value
values.remove(value)
break
res
But how do I added it to the dictionary without removing values? Any help is appreciated!
Upvotes: 2
Views: 206
Reputation: 31319
Something like this:
from pprint import pprint
my_list = [['Raji GlovesSixSixOneRegular price',
'Sale price$9.95',
' Save 67%'],
['Comp Vortex GlovesSixSixOneRegular price',
'Sale price$9.95',
' Save 67%'],
["Shasta 3/4 Cycling Tights - Women'sSpecializedRegular price",
'Sale price$14.95',
' Save 79%']]
my_dict = {
n + 1: d for n, d in enumerate(
dict(zip(['ItemName', 'SalePrice', 'Saving'], item)) for item in my_list
)
}
pprint(my_dict)
Result:
{1: {'ItemName': 'Raji GlovesSixSixOneRegular price',
'SalePrice': 'Sale price$9.95',
'Saving': ' Save 67%'},
2: {'ItemName': 'Comp Vortex GlovesSixSixOneRegular price',
'SalePrice': 'Sale price$9.95',
'Saving': ' Save 67%'},
3: {'ItemName': "Shasta 3/4 Cycling Tights - Women'sSpecializedRegular price",
'SalePrice': 'Sale price$14.95',
'Saving': ' Save 79%'}}
Note: pprint
is only there for the pretty dictionary, you don't need the import to make the code itself work.
The solution works like this:
ts = [(1, 'one'), (2, 'two')]
d = {number: name for number, name in ts}
enumerate()
function, which takes an iterable and returns an iterable that pairs each element with an index, for example:# this prints [(0, 'a'), (1, 'b'), (2, 'c')]
print(list(enumerate(['a', 'b', 'c'])))
0
, so that's why there's a + 1
after n
enumerate()
function gets the result of a generator expression dict(<something>) for item in my_list)
. An example of enumerating a generator expression:print(list(enumerate(n for n in range(10, 20))))
zip()
, which takes two iterables and pairs up the results, in this case the keys you want for your inner dictionaries ['ItemName', 'SalePrice', 'Saving']
and the lists in your original list, one by one, as handed to it by the generator expression. Try running just this:print(list(list(zip(['ItemName', 'SalePrice', 'Saving'], item)) for item in my_list))
That should give you some idea of what's going on.
Generally, if you receive a bit of code that works, but you can't really tell why, try to see how the expression fits together. If you really tease it apart, it looks like this:
my_dict = {
number + 1: dict_element
for number, dict_element in enumerate(
dict(
zip(['ItemName', 'SalePrice', 'Saving'], item)
)
for item in my_list
)
}
Then try if you understand each bit, starting with the inner parts. So, in this case, you'd want to figure out what zip()
does. Play around with the function, until you understand it, then go up a level, see what dict()
does with the result of a zip()
function. Once you get that, see why there's a for
after it (it's a generator), etc.
Of course, if you prefer your code to be short above anything else, this is the same, but hard to decipher:
d = {n+1: d for n, d in enumerate(dict(zip(['ItemName','SalePrice','Saving'], x)) for x in my_list)}
I appreciate you asking for an explanation, because it means you're trying to learn and not just copying answers - keep it up.
Upvotes: 2
Reputation: 712
If you wanna go real crazy, here is my solution in one line. It's hard to describe...
enumerate
basically returns us two items for each element in array, first is the index number the second is the real object. That way we can count it in-place. Then we assign it as key in outer dict, and as the value of that key we insert the inner dictionary with values from the array.
I also used .strip
function to remove unnecesary spaces etc.
from pprint import pprint
my_list = [['Raji GlovesSixSixOneRegular price',
'Sale price$9.95',
' Save 67%'],
['Comp Vortex GlovesSixSixOneRegular price',
'Sale price$9.95',
' Save 67%'],
["Shasta 3/4 Cycling Tights - Women'sSpecializedRegular price",
'Sale price$14.95',
' Save 79%']]
newDict = {i + 1: {"ItemName": arr[0].strip(), "SalePrice": arr[1].strip(), "Saving": arr[2].strip()} for i, arr in enumerate(my_list)}
pprint(newDict)
Also here is the basic equavilent of the solution above:
newDict = {}
for i, arr in enumerate(my_list):
newDict[i + 1] = {}
newDict[i + 1]["ItemName"] = arr[0]
newDict[i + 1]["SalePrice"] = arr[1]
newDict[i + 1]["Saving"] = arr[2]
pprint(newDict)
Here is another easy solution, here we define a dictionary and define a starting number as 1, iterating over the my_list
array and then we assign a dictionary in that iteration. Inside the dictionary we can fill in from the arr
object.
i = 1
newDict = {}
for arr in my_list:
newDict[i] = {
"ItemName": arr[0].strip(),
"SalePrice": arr[1].strip(),
"Saving": arr[2].strip(),
}
i += 1
Output
{1: {'ItemName': 'Raji GlovesSixSixOneRegular price',
'SalePrice': 'Sale price$9.95',
'Saving': 'Save 67%'},
2: {'ItemName': 'Comp Vortex GlovesSixSixOneRegular price',
'SalePrice': 'Sale price$9.95',
'Saving': 'Save 67%'},
3: {'ItemName': "Shasta 3/4 Cycling Tights - Women'sSpecializedRegular price",
'SalePrice': 'Sale price$14.95',
'Saving': 'Save 79%'}}
Upvotes: 2