1

I would like to sort the values of a dictionary (which are lists) based on one of the lists. For example say I have the dictionary:

data = {'AttrA':[2,4,1,3],'AttrB':[12,43,23,25],'AttrC':['a','d','f','z']}

and I would like to sort this based on the values associated with AttrA, such that:

data = {'AttrA':[1,2,3,4],'AttrB':[23,12,25,43],'AttrC':['f','a','z','d']}

Thank you in advance!

user8675309
  • 181
  • 2
  • 10
  • 2
    Simplify the question. It's has nothing to do with dictionaries, but rather is "How can I sort a list and then map other lists based on the sorted positions?" (Or, perhaps "How can I sort a list based on another list?") – user2246674 Jul 22 '13 at 20:40
  • sort first list, create a list of indices from it; apply indices to remaining lists. You probably have to make copies of lists unless you are clever. – Jiminion Jul 22 '13 at 20:40
  • Question is simple enough. – Jiminion Jul 22 '13 at 20:41
  • Apply the dupe question solution to *each* value in your dictionary, using the `AttrA` value as the 'input' list. – Martijn Pieters Jul 22 '13 at 20:42
  • I see the point, but sometimes when people 'simplify' questions, they leave out a salient point or typo that is very germane to solving the problem. – Jiminion Jul 22 '13 at 21:01

3 Answers3

6

Sort each value in your dictionary based on the data['AttrA'] source list, using sorted() and zip(), all in just 3 lines of code:

base = data['AttrA'] # keep a reference to the original sort order
for key in data:
    data[key] = [x for (y,x) in sorted(zip(base, data[key]))]

Demo:

>>> data = {'AttrA': [2, 4, 1, 3], 'AttrB': [12, 43, 23, 25], 'AttrC': ['a', 'd', 'f', 'z']}
>>> base = data['AttrA']
>>> for key in data:
...     data[key] = [x for (y,x) in sorted(zip(base, data[key]))]
... 
>>> data
{'AttrB': [23, 12, 25, 43], 'AttrC': ['f', 'a', 'z', 'd'], 'AttrA': [1, 2, 3, 4]}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1
from operator import itemgetter
data = {'AttrA':[2,4,1,3],'AttrB':[12,43,23,25],'AttrC':['a','d','f','z']}

sort = itemgetter(*[i for i, v in sorted(enumerate(data['AttrA']), key=itemgetter(1))])
data = dict((k, list(sort(v))) for k, v in data.items())

Or a shorter but less efficient method of creating sort:

sort = itemgetter(*[data['AttrA'].index(v) for v in sorted(data['AttrA'])])

Result:

>>> data
{'AttrB': [23, 12, 25, 43], 'AttrC': ['f', 'a', 'z', 'd'], 'AttrA': [1, 2, 3, 4]}

This uses operator.itemgetter to create a sorting function that grabs items from a sequence in the order determined by data['AttrA'], and then applying that sorting function to each value in the dictionary.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
0

Untested, but should work (or at least be a good place to start)

data = {'AttrA':[2,4,1,3],'AttrB':[12,43,23,25],'AttrC':['a','d','f','z']}
sortkey = 'AttrA'
sortedval = sorted(data['AttrA'])
valmaps = {i:sortedvals.find(num) for i,num in enumerate(data['AttrA'])}
newData = {k:[v[valmaps[i]] for i,_num in enumerate(v)] for k,v in data.items()}

Hope this helps

inspectorG4dget
  • 110,290
  • 27
  • 149
  • 241