NewBee
NewBee

Reputation: 1040

Create dictionary from a nested list

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

Answers (2)

Grismar
Grismar

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:

  • on the outside, you get a dictionary comprehension, turning an iterable of tuples into a dictionary; a simpler example is:
ts = [(1, 'one'), (2, 'two')]
d = {number: name for number, name in ts}
  • instead of passing in a list of tuples, like in that example, it gets the result of the 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'])))
  • You can see how that gets you what you need to fill the dictionary, except that it starts at 0, so that's why there's a + 1 after n
  • The 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))))
  • The generator exception uses 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

Guven Degirmenci
Guven Degirmenci

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

Related Questions