The information inside the arrays is in the "reverse" order of how I want it. Ideally it could be sorted by the dates within the array but I'm 100% certain just reversing the order would work.
By using something like this:
sorted(Dictionary[self], key=lambda i: i[1][0], reverse=True)
I know that the above JUST sorts the arrays themselves into reverse order and not the data inside the array into reverse order.
With the Dictionary like this (all items are a file name)
Dictionary = {'a':[XPJulianDay(Timefurthestinpastfromnow), ... XPJulianDay(timeclosest2currnttime)], 'b':[RQJulianDay(Timefurthestinpastfromnow), ... RQJulianDay(timeclosest2currnttime)], 'c':[WSJulianDay(Timefurthestinpastfromnow), ... WSJulianDay(timeclosest2currnttime)] ..... (9 different ones total) }
turning into this
Dictionary = {'a':[XPJulianDay(timeclosest2currnttime), ... XPJulianDay(Timefurthestinpastfromnow)], 'b':[RQJulianDay(timeclosest2currnttime), ... RQJulianDay(Timefurthestinpastfromnow)], 'c':[WSJulianDay(timeclosest2currnttime), ... WSJulianDay(Timefurthestinpastfromnow)] .... }
You can try that:
Dictionary.update({ k: sorted(v) for k, v in Dictionary.items() })
It updates the dictionary with its own keys, with sorted values.
Example:
>>> Dictionary = {"a": [7,6,1,2], "b": [8,0,2,5] }
>>> Dictionary.update({ k: sorted(v) for k, v in Dictionary.items() })
>>> Dictionary
{'a': [1, 2, 6, 7], 'b': [0, 2, 5, 8]}
>>>
Note that a new dictionary is created for the call to .update() using a dict comprehension.
If needed you can replace sorted() by reversed() ; but reversed() returns an iterator so if you want a list you need to call it with list() (it is better to keep the iterator if you can).
Example with reversed:
>>> Dictionary = {"a": [7,6,1,2], "b": [8,0,2,5] } ; Dictionary.update({ k: reversed(v) for k, v in Dictionary.items() })
>>> Dictionary
{'a': <list_reverseiterator object at 0x7f537a0b3a10>, 'b': <list_reverseiterator object at 0x7f537a0b39d0>}
>>>
You can use the dict comprehension as stated by #mguijarr or use dict and zip
Dictionary = dict(zip(Dictionary, map(sorted, Dictionary.values()))))
But if your keys really are just the 'a', 'b', ... then why are you using a dict? Just use a list...
Related
I'm using Aiohttp's implementation of multidict().
Take this:
>>> d = MultiDict[('a', 1), ('b', 2), ('a', 3)])
>>> d
<MultiDict {'a': 1, 'b': 2, 'a': 3}>
I want to convert d to a regular dictionary where duplicate key values are appended into a list such as this:
{'a': [1, 3], 'b': 2}
Is there an elegant way to convert this? Other than a loop through items and a lot of logical conditions?
It doesnt look like multidicts have an inbuilt function for a straight conversion, but you can use the .keys() function to iterate through the multidict and copy the values into a fresh dictionary.
new_dict = {}
for k in set(multi_dict.keys()):
new_dict[k] = multi_dict.getall(k)
Two interesting things here - we need to make a set of the multidict keys function call to remove duplicates, and multidicts have a .getall() function that returns a list of all values associated with duplicate keys.
EDIT for single value cases:
new_dict = {}
for k in set(multi_dict.keys()):
k_values = multi_dict.getall(k)
if len(k_values) > 1:
new_dict[k] = k_values
else:
new_dict[k] = k_values[0]
I have a dict of dicts.
Example:
scores[i][subentity_type] = the_score
It looks like this:
scores = {0:{'SD':1,'ED':2},1:{'SD':0.5,'ED':3}}
so i would want a function that returns
'SD' --> 0
'ED' --> 1
for each subentity_type, I want to find the key i with the highest score.
do you have an idea if there is a python function to provide this?
thanks!
There is a max() method that accepts an array and determines the max value.
You can turn the values of a dict into a list with mydict.values() or as a generator v for v in mydict.values().
You however have a dict of dicts. You can iterate through it with for dictofdict in mydict.values()
-> Resulting code:
>>> mydict={'a': {'aa': 3, 'ab':7},
... 'b': {'ba': 5, 'bb':9}}
>>> [v for dictofdict in mydict.values() for v in dictofdict.values()]
[3, 7, 5, 9]
>>> max([v for dictofdict in mydict.values() for v in dictofdict.values()])
9
A dict of dict where you get the highest value.
Since you haven't actually explained how your final output should look like but I think you can sort the dict items based on values and get the key with highest value. Taking the example for Tin's answer
mydict={'a': {'aa': 3, 'ab':7},
'b': {'ba': 5, 'bb':9}}
new_dict ={}
for k in mydict.keys():
new_dict[k] = sorted(mydict[k].items(), key= lambda v:-v[1])[0][0]
#new_dict = {'a': 'ab', 'b': 'bb'}
Title pretty much says it all, I'm looking to efficiently sort a dictionary of parallel lists.
unsorted_my_dict = {
'key_one': [1,6,2,3],
'key_two': [4,1,9,7],
'key_three': [1,2,4,3],
...
}
sorted_my_dict = {
'key_one': [1,6,3,2],
'key_two': [4,1,7,9],
'key_three': [1,2,3,4],
...
}
I want to sort key_three, and all the other lists in that dictionary in parallel. There are a few similar questions but I'm struggling because I have an unknown number of keys in the dictionary to be sorted, and I only know the name of the key I want to sort on (key_three).
Looking to to do this with vanilla Python, no 3rd party dependencies.
Edit 1:
What do I mean by in parallel? I mean that if I sort key_three, which requires swapping the last two values, that all other lists in the dictionary will have their last two values swapped as well.
Edit 2: Python 3.4 specifically
You can first sort an enumerate of the target list to recover the desired order of indices and then rearrange each list in that order.
my_dict = {
'key_one': [1,6,2,3],
'key_two': [4,1,9,7],
'key_three': [1,2,4,3],
}
def parallel_sort(d, key):
index_order = [i for i, _ in sorted(enumerate(d[key]), key=lambda x: x[1])]
return {k: [v[i] for i in index_order] for k, v in d.items()}
print(parallel_sort(my_dict, 'key_three'))
Output
{'key_one': [1, 6, 3, 2],
'key_two': [4, 1, 7, 9],
'key_three': [1, 2, 3, 4]}
zip the keys together, sort on a key function based on the relevant item, , then zip again to restore the original form:
sorted_value_groups = sorted(zip(*unsorted_my_dict.values()), key=lambda _, it=iter(unsorted_my_dict['key_three']): next(it))
sorted_values = zip(*sorted_value_groups)
sorted_my_dict = {k: list(newvals) for k, newvals in zip(unsorted_my_dict, sorted_values)}
Not at all clean, I mostly just posted this for funsies. One-liner is:
sorted_my_dict = {k: list(newvals) for k, newvals in zip(unsorted_my_dict, zip(*sorted(zip(*unsorted_my_dict.values()), key=lambda _, it=iter(unsorted_my_dict['key_three']): next(it))))}
This works because, while dict iteration order isn't guaranteed prior to 3.7, the order is guaranteed to be repeatable for an unmodified dict. Similarly, the key function is executed in order from start to finish, so pulling the key by repeated iteration is safe. We just detach all the values, group them by index, sort the groups by the index key, regroup them by key, and reattach them to their original keys.
Output is exactly as requested (and the order of the original keys is preserved on CPython 3.6 or any Python 3.7 or higher):
sorted_my_dict = {
'key_one': [1,6,3,2],
'key_two': [4,1,7,9],
'key_three': [1,2,3,4]
}
First with the given key on which sorting is done, you can get the indices order. You that sequence to rearrange the remaining lists in the dictionary.
unsorted_my_dict = {
'key_one': [1, 6, 2, 3],
'key_two': [4, 1, 9, 7],
'key_three': [1, 2, 4, 3],
}
def sort_parallel_by_key(my_dict, key):
def sort_by_indices(idx_seq):
return {k: [v[i] for i in idx_seq] for k, v in my_dict.items()}
indexes = [idx for idx, _ in sorted(enumerate(my_dict[key]), key=lambda foo: foo[1])]
return sort_by_indices(indexes)
print(sort_parallel_by_key(unsorted_my_dict, 'key_three'))
I am trying to build a dict from a set of unique values to serve as the keys and a zipped list of tuples to provide the items.
set = ("a","b","c")
lst 1 =("a","a","b","b","c","d","d")
lst 2 =(1,2,3,3,4,5,6,)
zip = [("a",1),("a",2),("b",3),("b",3),("c",4),("d",5)("d",6)
dct = {"a":1,2 "b":3,3 "c":4 "d":5,6}
But I am getting:
dct = {"a":1,"b":3,"c":4,"d":5}
here is my code so far:
#make two lists
rtList = ["EVT","EVT","EVT","EVT","EVT","EVT","EVT","HIL"]
raList = ["C64G","C64R","C64O","C32G","C96G","C96R","C96O","RA96O"]
# make a set of unique codes in the first list
routes = set()
for r in rtList:
routes.add(r)
#zip the lists
RtRaList = zip(rtList,raList)
#print RtRaList
# make a dictionary with list one as the keys and list two as the values
SrvCodeDct = {}
for key, item in RtRaList:
for r in routes:
if r == key:
SrvCodeDct[r] = item
for key, item in SrvCodeDct.items():
print key, item
You don't need any of that. Just use a collections.defaultdict.
import collections
rtList = ["EVT","EVT","EVT","EVT","EVT","EVT","EVT","HIL"]
raList = ["C64G","C64R","C64O","C32G","C96G","C96R","C96O","RA96O"]
d = collections.defaultdict(list)
for k,v in zip(rtList, raList):
d[k].append(v)
You may achieve this using dict.setdefault method as:
my_dict = {}
for i, j in zip(l1, l2):
my_dict.setdefault(i, []).append(j)
which will return value of my_dict as:
>>> my_dict
{'a': [1, 2], 'c': [4], 'b': [3, 3], 'd': [5, 6]}
OR, use collections.defaultdict as mentioned by TigerhawkT3.
Issue with your code: You are not making the check for existing key. Everytime you do SrvCodeDct[r] = item, you are updating the previous value of r key with item value. In order to fix this, you have to add if condition as:
l1 = ("a","a","b","b","c","d","d")
l2 = (1,2,3,3,4,5,6,)
my_dict = {}
for i, j in zip(l1, l2):
if i in my_dict: # your `if` check
my_dict[i].append(j) # append value to existing list
else:
my_dict[i] = [j]
>>> my_dict
{'a': [1, 2], 'c': [4], 'b': [3, 3], 'd': [5, 6]}
However this code can be simplified using collections.defaultdict (as mentioned by TigerhawkT3), OR using dict.setdefault method as:
my_dict = {}
for i, j in zip(l1, l2):
my_dict.setdefault(i, []).append(j)
In dicts, all keys are unique, and each key can only have one value.
The easiest way to solve this is have the value of the dictionary be a list, as to emulate what is called a multimap. In the list, you have all the elements that is mapped-to by the key.
EDIT:
You might want to check out this PyPI package: https://pypi.python.org/pypi/multidict
Under the hood, however, it probably works as described above.
Afaik, there is nothing built-in that supports what you are after.
I need to select elements of a dictionary of a certain value or greater. I am aware of how to do this with lists, Return list of items in list greater than some value.
But I am not sure how to translate that into something functional for a dictionary. I managed to get the tags that correspond (I think) to values greater than or equal to a number, but using the following gives only the tags:
[i for i in dict if dict.values() >= x]
.items() will return (key, value) pairs that you can use to reconstruct a filtered dict using a list comprehension that is feed into the dict() constructor, that will accept an iterable of (key, value) tuples aka. our list comprehension:
>>> d = dict(a=1, b=10, c=30, d=2)
>>> d
{'a': 1, 'c': 30, 'b': 10, 'd': 2}
>>> d = dict((k, v) for k, v in d.items() if v >= 10)
>>> d
{'c': 30, 'b': 10}
If you don't care about running your code on python older than version 2.7, see #opatut answer using "dict comprehensions":
{k:v for (k,v) in dict.items() if v > something}
While nmaier's solution would have been my way to go, notice that since python 2.7+ there has been a "dict comprehension" syntax:
{k:v for (k,v) in dict.items() if v > something}
Found here: Create a dictionary with list comprehension in Python. I found this by googling "python dictionary list comprehension", top post.
Explanation
{ .... } includes the dict comprehension
k:v what elements to add to the dict
for (k,v) in dict.items() this iterates over all tuples (key-value-pairs) of the dict
if v > something a condition that has to apply on every value that is to be included
You want dict[i] not dict.values(). dict.values() will return the whole list of values that are in the dictionary.
dict = {2:5, 6:2}
x = 4
print [dict[i] for i in dict if dict[i] >= x] # prints [5]