1

I'm trying to use a python dictionary so that each key has a list of strings so that any individual string from that list can be interpreted as they key itself. Not sure if that's the proper use of a dictionary or not. Relatively new to this world. Alternate solutions are welcome.

facilities = {'Name 1': ['Abr. 1', 'Alternate Name 1', 'Name1', 'Name #1'],
              'Name 2': ['Abr. 2', 'Alternate Name 2', 'Name2', 'Name #2', 'Nm. 2'],
              'Name 3': ['Abr 3', 'Alt Name 3', 'Name3', 'Nm. 3']}

user_input1 = 'Alternate Name 2'

user_input2 = 'Nm 3.'

user_input3 = 'Abr. 1'

user_input4 = 'Alternate Name 1'

I'd then do some sort of operation so that operation(user_input) would return either 'Name 1', 'Name 2', or 'Name 3', depending on the value of user_input (assuming it's in one of the 3 defined lists). The 4 user_inputs listed above would produce 'Name3', 'Name2', 'Name1', and 'Name 1', respectively.

JB-747
  • 11
  • 3

3 Answers3

2

Here's one way to do it for user_input1.

[k for k, v in facilities.items() if user_input1 in v]

And of course you could wrap this in a function:

def parse_user_input(user_input):
    return [k for k, v in facilities.items() if user_input in v]
William
  • 381
  • 1
  • 8
  • This got me what I needed. I thought list comprehension might get me there, just couldn't quite figure it out. I appreciate the help. – JB-747 Apr 28 '21 at 04:24
  • @JB-747 If this helped out, could you upvote? The upvote means "the answer is useful" (Even if you don't choose this as the answer, the cred points would help, thanks) – William May 26 '21 at 01:32
  • I’d love to. Just tried, but it looks like I don’t have enough points to do this yet. System told me I need 15 points to vote and I only have 11. – JB-747 May 27 '21 at 02:05
  • Ahh gotcha forgot about that! Thanks for trying! – William May 27 '21 at 17:15
0

You could just create another dict that reverses the mapping but also flattens out the alias lists. So there are multiple dict entries pointing back to the same string.

We can test it by iterating over all the aliases and checking they point back to the same name.

facilities = {'Name 1': ['Abr. 1', 'Alternate Name 1', 'Name1', 'Name #1'],
              'Name 2': ['Abr. 2', 'Alternate Name 2', 'Name2', 'Name #2', 'Nm. 2'],
              'Name 3': ['Abr 3', 'Alt Name 3', 'Name3', 'Nm. 3']}

revmap = {alias: k for k, v in facilities.items() for alias in v}

from itertools import chain
for alias in chain.from_iterable(facilities.values()):
    print('%s => %s' % (alias, revmap[alias]))
Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
  • 1
    This certainly more elegantly makes use of dictionaries. Though I guess this approach would not allow for collisions (a reasonable assumption that the mapping is unique given the question). – William Apr 28 '21 at 04:21
  • @William you are absolutely correct. It might be better that it gives an error if such a collision occurs. After all they are aliases. So you'd want to know if they were ambiguous. The other solution has a similar issue though. In the case of a collision it would pick the first one it found, whereas in this solution later duplicates would replace earlier ones in the dict. – Paul Rooney Apr 28 '21 at 04:39
0

Thanks! With the above two answers and discussion, I came up with this function to create a new dictionary. It protects against inputs resulting in ambiguous mappings. I also realized I needed the original keys to map to themselves, for cases where the user_input is one of the original keys, so it just returns itself.

def alias_lookup_dict(alias_dict):
    
    # Get List of all Aliases
    aliases_flat = [item for sublist in list(alias_dict.values()) for item in sublist]
    
    # Create a reversed and flattened dictionary
    rev_alias_dict = {alias: k for k, v in alias_dict.items() for alias in v}
    
    # Create a dictionary mapping the original keys to themselves
    orig_keys = {k: k for k in alias_dict.keys()}
    
    # If no potential for ambiguous mappings, merge rev_alias_dict and orig_keys
    if len(aliases_flat) == len(set(aliases_flat)):
        
        # Merge dict w/ original keys mapped to themselves w/ the reversed/flattened dict
        rev_alias_dict.update(orig_keys)
        return rev_alias_dict
        
    # If potential for ambiguous mappings, return empty dictionary and print warning
    else:
        
        return {}        
        print('Repeated aliases detected.  Potential for ambiguous mappings.')
JB-747
  • 11
  • 3