occvtech occvtech - 2 years ago 141
Python Question

Python - how to access values in dictionary that were added by user input?

Say I have an empty dictionary that a user adds an arbitrary number of items into. After the user adds items to the dictionary, I want to then loop through that dictionary and be able to pull values out of it. What is the best way to access the items in the dictionary since I don't know the name of the key?

For example say I have the following:

# my shopping cart that starts off empty
shopping_cart = {}

# user enters how many items they will have in the cart total
total_items = input("How many items will you add to your cart? ")

# User adds both the value and the key of each item to add
for i in total_items:
name = input("Enter name of item to add: ")
location = input("Is the item in front, middle, or back of cart? ")

shopping_cart[name] = location


At this point I have a
shopping_cart
dictionary, but I don't have a way to know what the KEYs or VALUEs are.

..... Now say there is some large string of thousands of characters in random order called
random_string
. It looks like "axdfebzsdcdslapplefjdkslazpair....." Notice how the string is random, but periodically there are names of items like "apple" and "pair".

What I want to do is loop my
shopping_cart
dictionary and find the next index position within my
random_string
where the item in my
shopping_cart
appears.

For example - let's say the user adds 3 items to the shopping cart. The items are "donkey", "apple", "pair".

What I want to do is read through the
random_string
in order, and return the dictionary value that appears next in the string. I.E. in this case, "apple" is the next item in the random string, so it should be returned so I can lookup the value of "apple" in the dictionary and get the location of the item.

I have working code to do everything that is necessary EXCEPT for knowing how to pull the Keys out of the dictionary. I've copied a line below that essentially shows what I'm trying to accomplish. The problem is I don't know what DICT_KEY is, because it was added by the user.

index = random_string.find([DICT_KEY], index)


........ Not to confuse things, but I'm considering making an empty list that mirrors the dictionary values. In other words, when the user adds the item "apple" to the dictionary, I could add it to the dictionary and to the list. That way I can lookup the item in the dictionary by using it's index position in the list. seems like a bad way to handle this though, so happy to get any advice you can offer...

As you can see, I'm new at this!

Answer Source
>>> a={'apple':'front','donkey':'middle','pair':'back'}
>>> s='asdfhskdfksjdf;ksjapplefsakdjfskdjfapplesdfksdjdonkeydlkfjsldjfdpair'
>>> {k:[m.start() for m in re.finditer(k,s)] for k in a}
{'pair': [64], 'donkey': [47], 'apple': [18, 35]}

This one found two apple, one donkey and one pair in the string at indices 18/35/47/64.


Explanation
Follow up on the commands used earlier

Create a new dictionary with the keys I have and assign a constant value.

>>> a
{'pair': 'back', 'donkey': 'middle', 'apple': 'front'}
>>> {k:0 for k in a}
{'pair': 0, 'donkey': 0, 'apple': 0}

That allows us to make a dictionary with each key having same value 0. a being the dictionary you already made.

Now let's see how we set the values to indices of these words in the big string.

>>> [m.start() for m in re.finditer('apple',s)]
[18, 35]

re.finditer returns as many matches in s for apple.
For each match m thus found, m.start() returns the start index of the match.
Now this gives a list of indices where apple is appearing in the string.

Finally if we combine the above two we get a dictionary with our original keys. And values as a list of indices where they appear in the string.

>>> {k:[m.start() for m in re.finditer(k,s)] for k in a}
{'pair': [64], 'donkey': [47], 'apple': [18, 35]}

UPDATE2
After new req. in comments

>>> d={k:[m.start() for m in re.finditer(k,s)] for k in a}
>>> from collections import defaultdict
>>> nd=defaultdict(list)
>>> for k in d:
...   nd[a[k]].extend(d[k])
... 
>>> dict(nd)
{'front': [18, 35], 'middle': [47], 'back': [64]}

If you do not want to go twice over then..

>>> from collections import defaultdict
>>> nd=defaultdict(list)
>>> for k in a:
...   for m in re.finditer(k,s):
...     nd[a[k]].append(m.start())
... 
>>> dict(nd)
{'front': [18, 35], 'middle': [47], 'back': [64]}

UPDATE3

>>> {(k,a[k]):[m.start() for m in re.finditer(k,s)] for k in a}
{('pair', 'back'): [64], ('apple', 'front'): [18, 35], ('donkey', 'middle'): [47]}
>>> {m.start():(k,a[k]) for k in a for m in re.finditer(k,s)}
{64: ('pair', 'back'), 18: ('apple', 'front'), 35: ('apple', 'front'), 47: ('donkey', 'middle')}

UPDATED

If indices are more important for you then do the below

>>> {m.start():k  for k in a for m in re.finditer(k,s)}
{64: 'pair', 18: 'apple', 35: 'apple', 47: 'donkey'}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download