3

I'm working with openpyxl to read and write xlsx files, for some data manipulation purposes I need to translate my worksheet (which I have represented in a 2D matrix) into a dictionary which follows a specific format, here is my matrix.

[['Name', 'Age', 'Gender', 'Height', 'Hair Color'],
 ['Jay', '12', 'M', '123cm', 'Black'],
 ['Marie', '13', 'F', '100cm', 'Red'],
 ['Dan', '16', 'M', '200cm', 'Brown']
]

I'd like to translate this so that the resulting dictionary looks like:

{

{ 'Jay;12;M' : 'Name': 'Jay', 'Age': '12', 'Gender': 'M', 'Height': '123cm', 'Hair Color' : 'Black'}, 

{ 'Marie;13;F' : 'Name': 'Marie', 'Age': '13', 'Gender': 'F', 'Height': '100cm', 'Hair Color' : 'Red'},

{ 'Dan;16;M' : 'Name': 'Dan', 'Age': '16', 'Gender': 'M', 'Height': '200cm', 'Hair Color' : 'Brown'},

}

I'm relatively new to Python and I believe a dictionary comprehension is the way to go but I'm not exactly sure how to get these 2D array values by name so I can build my key value pairs properly.

mvw
  • 5,075
  • 1
  • 28
  • 34
Felipe Rios
  • 101
  • 2
  • 10
  • The 2D array has no names, you need to address the contents by providing numerical index values to pick the wanted array and its wanted element. – mvw Sep 24 '15 at 22:52
  • You can do something like this `my_dict[my_array[0][y]] = my_array[x][y]` inside a loop. Also, just fyi, typo in your dictionary. should look like `'Jay;12;M' : {'Name': 'Jay', 'Age': '12' ...` etc – ate50eggs Sep 24 '15 at 22:58

1 Answers1

5

Assuming you want this format:

{'<name>;<age>;<gender>': {'Name': <name>, 'Age': <age>, 'Gender': <gender>, 'Height': <height>: 'Hair Color': <hair_color>}}

Having:

  • l: your multidimensional array
  • k: first row (keys)

Try this:

{reduce(lambda x, y : '{0};{1}'.format(x,y), l[j]):{k[i]: l[j][i] for i in range(len(k))} for j in range(1, len(l))}

This list comprehension iterates through all the rows of l (except the first one) and for each one, creates a dictionary whose keys are the elements of k and the values are the elements of the current l's row.

UPDATE

You can pass another iterable to reduce function instead of l[j] (the complete row). For your case could be: l[j][:3] instead of l[j], see the use of slices. So the above should have: reduce(lambda x, y : '{0};{1}'.format(x,y), l[j][:3]).

Also, the use of zip() can make a little bit more elegant the creation of the inner dictionaries:

r = {reduce(lambda x, y : '{0};{1}'.format(x,y), l[j][:3]):{t[0]: t[1] for t in zip(k, l[j])} for j in range(1, len(l))}
Community
  • 1
  • 1
Robin Curbelo
  • 1,323
  • 1
  • 11
  • 21
  • 1
    This definitely works but it gives me a key that consists of all the values, I only need it for 3 specific values in the dictionary, so I'll tweak this a bit more to make it work, thanks. – Felipe Rios Sep 24 '15 at 23:10