0

I have two lists

system = ['System A', 'System B', 'System C']
instrument = ['Instrument 1', 'Instrument 2', 'Instrument 3', 'Instrument 4']

The system items may correspond from one to several instrument items, like this:

dict = {'System A':['Instrument 1', 'Instrument 2'], 'System B':['Instrument 3'], 'System C':['Instrument 4']}

Notice how 'System A' has one list value that is built upon the first two items from instrument list

To illustrate better my problem:
Systems and instruments table

I tried a dict comprehension + zip() but obviously it didn't work. This is what I tried:

system_data_dict = {sys:inst for sys, inst in zip(system, instrument)}

Please note that this isn't a CSV problem. The data that I'm aquiring is from a SQL Database and I need to parse it

I'm banging my head to the keyboard right now lol.

Thanks in advance

Edit: the system list has been parsed with set()

  • 1
    How does the grouping work? Why did `System A` take both `Instrument 1` and `Instrument 2` from the second list, what stopped `System B` from taking `Instrument 2` and `Instrument 3` instead? what is the logic here? – Chase Sep 25 '20 at 05:33
  • Precisely. There is no assignment given. How is the program to know? – roadrunner66 Sep 25 '20 at 05:35
  • @Chase this is data stored in a database, and I'm getting it row by row. I made a mistake in not clarifying that the first list is a set() of the data aquired. I'll edit it right now – WhiteHeadbanger Sep 25 '20 at 05:49

2 Answers2

0

Python does not have multidicts, so you have two options:

  1. use multidicts from an existing library e.g. werkzeug's MultiDict, when initialised with lists of pairs, will associate multiple values to keys which are present multiple times (unlike dict which will only keep the last value)

    system_data_dict = werkzeug.datastructures.MultiDict(zip(system, instrument))
    system_data_dict.getlist('System A') # => ['Instrument 1', 'Instrument 2']
    
  2. alternatively, do that by hand by using a regular loop, even if it's feasible using a comprehension (which I'm not sure about) it's going to look dreadful: use a defaultdict or the dict.setdefault method to define a dict mapping keys to lists and append values every time

    system_data_dict = {}
    for k, v in zip(system, instrument):
       system_data_dict.setdefault(k, []).append(v)
    system_data_dict['System A'] # => ['Instrument 1', 'Instrument 2']
    
Masklinn
  • 34,759
  • 3
  • 38
  • 57
-1

Give a grouping info to your list.

Assuming you are getting items from a database,

SELECT System, instrument FROM <src> WHERE System IN ("System A", "System B", "System C")

and parsing it to form a list like:

items = [("System A", "Instrument 1"), ("System A", "Instrument 2"), ("System B", "Instrument 3"), ...]

then use your dictionary code:

# system_data_dict = {sys:inst for sys, inst in items}

# EDIT
system_data_dict = {}
for sys, inst in items:
    if sys in system_data_dict.keys():
        system_data_dict[sys].append(inst)
    else:
        system_data_dict[sys] = [inst]
Joonyoung Park
  • 474
  • 3
  • 6
  • 1
    Doesn't work, if a key is present multiple times in the input then only the last associated value will be in the final dict. – Masklinn Sep 25 '20 at 06:05
  • The items list works as expected, but when I try to convert it to a dict, only the last (key, value) is stored. I tried also this: system_data_dict = {sys:[inst] for sys, inst in items} but it's the same result – WhiteHeadbanger Sep 25 '20 at 06:06
  • @Masklinn Sorry. Wasn't thinking straight. Made an edit so the value is a list now. – Joonyoung Park Sep 25 '20 at 06:26