I have a dictionary with tuple keys, like so:
(1111, 3454): 34.55555
(1123, 4665): 67.12
(1111, 9797): 5.09
I need to do a list comprehension that grabs the values for all entries with a matching first element.
Problem is, I ALSO need that second value of the tuple...
interimlist = [v for k,v in mydict.items() if k[0]==item[0]]
Is what I've got right now for pulling the values if the first element of the tuple is correct (item is an iterator variable). I'd like the output to be a list of tuples of (value, second tuple number), so with the example points, would be the following output if item[0] is 1111:
[(34.55555, 3454), (5.09, 9797)]
The dict is not stored with a good with a good structure here. All the keys/vals must be iterated in order to do one lookup, so it is O(n) retrieval.
You should do a once-off re-keying of the data, adding another level of nesting in the dict:
>>> d
{(1111, 3454): 34.55555, (1123, 4665): 67.12, (1111, 9797): 5.09}
>>> d_new = {}
>>> for (k1, k2), v in d.items():
... if k1 not in d_new:
... d_new[k1] = {}
... d_new[k1][k2] = v
And now, O(1) lookups are restored:
>>> d_new[1111]
{3454: 34.55555, 9797: 5.09}
>>> [item[::-1] for item in d_new[1111].items()]
[(34.55555, 3454), (5.09, 9797)]
Related
Let's assume that there is a dictionary list like this one:
lst = {(1,1):2, (1,2):5, (1,3):10, (1,4):14, (1,6):22}
I want a simple (the most efficient) function that returns the dictionary key which its value is the maximum.
For example:
key_for_max_value_in_dict(lst) = (1,6)
because the tuple (1,6) has the most value (22).
I came up with this code which might be the most efficient one:
max(lst, key=lambda x: lst[x])
Use a comprehension for that like:
Code:
max((v, k) for k, v in lst.items())[1]
How does it work?
Iterate over the items() in the dict, and emit them as tuples of (value, key) with the value first in the tuple. max() can then find the largest value, because tuples sort by each element in the tuple, with first element matching first element. Then take the second element ([1]) of the max tuple since it is the key value for the max value in the dict.
Test Code:
lst = {(1,1):2, (1,2):5, (1,3):10, (1,4):14, (1,6):22}
print(max((v, k) for k, v in lst.items())[1])
Results;
(1, 6)
Assuming you're using a regular unsorted dictionary, you'll need to walk down the entire thing once. Keep track of what the largest element is and update it if you see a larger one. If it is the same, add to the list.
largest_key = []
largest_value = 0
for key, value in lst.items():
if value > largest_value:
largest_value = value
largest_key = [key]
elif value == largest_value:
largest_key.append(key)
I have written a simple script the scope of which is:
list=[1,19,46,28 etc...]
dictionary={Joey:(10,2,6,19), Emily: (0,3), etc}
Now I need to find all the keys of the dictionary which have at least one of the list entries in the values
Example: 19 is in Joeys values, so Joey is the winner.
How I did it: (no programmer at all)
# NodesOfSet = the list
# elementsAndTheirNodes = the dictionary
# loop as many times as the number of key:value entries in the dictionary element:nodes
# simply: loop over all the elements
for i in range (0, len (elementsAndTheirNodes.keys())):
# there is an indent here (otherwise it wouldnt work anyway)
# loop over the tuple that serves as the value for each key for a given i-th key:value
# simply: loop over all their nodes
for j in range (0, len (elementsAndTheirNodes.values()[i])):
# test: this prints out element + 1 node and so on
# print (elementsAndTheirNodes.keys()[i], elementsAndTheirNodes.values()[i][j] )
for k in range (0, len (NodesOfSet)):
if NodesOfSet[k] == (elementsAndTheirNodes.values()[i][j]):
print ( elementsAndTheirNodes.keys()[i], " is the victim")
else:
print ( elementsAndTheirNodes.keys()[i], " is not the victim")
But this is very time consuming as it iterates over basically everything in the database. May I ask for a help optimizing this? Thanks!
I would use a list comprehension and the builtin any which shortcircuits once a shared item is found. Turning your list into a set reduces the complexity of the membership lookup from O(n) to O(1):
s = set(lst)
result = [k for k, v in dct.items() if any(i in s for i in v)]
Be careful to not assign builtins as the names for your objects (e.g. list) to avoid making the builtin unusable later on in your code.
Don't use the name list, list is the name of a library function.
l = [1, 19, 46, 28, ...]
l_set = set(l)
d = {'Joey':(10,2,6,19), 'Emily': (0,3), ...}
winners = [k for k, v in d.items() if any(i in l_set for i in v)]
any will stop iterating through v as soon as it "sees" a shared value, saving some time.
You could also use set intersection to check if any of the elements in the dictionary value tuples have anything in common with your "list" entries:
l = [1,19,46,28, ...]
s = set(l)
d = {Joey:(10,2,6,19), Emily: (0,3), ...}
winners = [k for k, v in d.iteritems() if s.intersection(v)]
I'm trying to understand about dictionaries and list in Python.
Assume that I have a list which contains 3 dictionaries
Ex. item_list = [price,stock,quantity]
price, stock and quantity are the dictionaries here. Each dictionary has few key-value pairs like
price = {'toys':25,'clothes':[12,15,20]}
I know to access individual elements, I can use a for loop with the keys specified like:
for item in item_list:
print item['toys']
How do I access the elements without directly mentioning the key in the for loop?
You can iterate over a dictionary just like you can iterate over a list.
for item in item_list:
for key in item:
print item[key]
In a sense, you're still mentioning the keys, but you're not referencing them explicitly by their value.
If you're just interested in the values you can use the values() method:
for item in item_list:
for key in item.values():
print item[key]
My preferred way to iterate over dictionaries though is with items, which returns a tuple of key, value pairs.
for item in item_list:
for key, value in item.items():
print key, value
I would do something like this:
for item in item_list:
for key, value in item.iteritems():
print key, value
Let us say, you have a list like this
prices_list = [{'toys':25,'clothes':[12,15,20]},{'toys':35,'clothes':[12,15,20]}]
And you would like to get the value corresponding to toys, but without specifying the name in the for loop. So, you can use operator.itemgetter like this
from operator import itemgetter
getter = itemgetter("toys")
print [getter(item) for item in prices_list]
# [25, 35]
The same can be used like this
total = 0
for item in prices_list:
total += getter(item)
for d in item_list:
for i in d.values():
print i
You could also call d.items() and get back tuples of (key, value) if you wanted access to both.
Additionally if you don't care about readability you could use this to get a list of all the values accross the dicts in your list.
[x for y in (i.values() for i in item_list) for x in y]
You can also use: [d for i in item_list for d in i.values()] to get the values and flatten them into a list (though yours would still be nested because of clothes' value being a list.
Finally you can merge the dictionaries into one if they have distinct keys:
joint_mapping = dict([d for i in item_list for d in i.items()])
or if they don't have unique values you can use the below code to produce a dict of lists of values. :
for k, v in [d for i in item_list for d in i.items()]:
new_d[k] = new_d.get(k, [])+[v]
You mentioned :
#Eenvincible - I would be inputting those values to other variable.
Print is just an example I gave. So would not want to hardcode the key.
I think you can do your trick using for loop as mentioned in other answers.
for item in item_list:
for key in item:
print item[key]
tempvariable = item[key]
.... do something here.
If you want to assign each value to a seperate variable, you should:
- First, assign that variables to any insignificant value EX: **None** or *""*
- Then, dynamically use the for loop to reassign each variable to new value using if condition or thier index.
EX:
price_toys , price_clothes , stock_toys , stock_clothes = None , None , None , None
for item in item_list:
for key in item:
tempvariable = item[key]
# condition to choose which varible will be set to the current value.
if item == "price" and key == "toys":
price_toys = tempvariable
# and so on
Let's say I have dict. I don't know the key/value inside. How do I get this key and the value without doing a for loop (there is only one item in the dict).
You might wonder why I am using a dictionary in that case. I have dictionaries all over my API and I don't want the user to be lost. It's only a matter of consistency. Otherwise, I would have used a list and indexes.
Use the proper data type for the job. Your goal should be to have workable code, not that you use the same data type all over the place.
If your dictionary only contains one key and one value, you can get either with indexing:
key = list(d)[0]
value = list(d.values())[0]
or to get both:
key, value = list(d.items())[0]
The list calls are needed because in Python 3, .keys(), .values() and .items() return dict views, not lists.
Another option is to use sequence unpacking:
key, = d
value, = d.values()
or for both at the same time:
(key, value), = d.items()
Just get the first item in the dictionary using an iterator
>>> d = {"foo":"bar"}
>>> k, v = next(iter(d.items()))
>>> k
'foo'
>>> v
'bar'
You can do this:
>>> d={1:'one'}
>>> k=list(d)[0]
>>> v=d[k]
Works in Python 2 or 3
d.popitem() will give you a key,value tuple.
I wrote the below code working with dictionary and list:
d = computeRanks() # dictionary of id : interestRank pairs
lst = list(d) # tuples (id, interestRank)
interestingIds = []
for i in range(20): # choice randomly 20 highly ranked ids
choice = randomWeightedChoice(d.values()) # returns random index from list
interestingIds.append(lst[choice][0])
There seems to be possible error because I'm not sure if there is a correspondence between indices in lst and d.values().
Do you know how to write this better?
One of the policies of dict is that the results of dict.keys() and dict.values() will correspond so long as the contents of the dictionary are not modified.
As #Ignacio says, the index choice does correspond to the intended element of lst, so your code's logic is correct. But your code should be much simpler: d already contains IDs for the elements, so rewrite randomWeightedChoice to take a dictionary and return an ID.
Perhaps it will help you to know that you can iterate over a dictionary's key-value pairs with d.items():
for k, v in d.items():
etc.