-2

I have the following dictionary:

my_dict = {"user": [1, 2, 3, 4], "sex": ['M', 'F', 'O', 'F'],"timeOfArrival": [4, 1, 3, 8]}

and I want to find a way to sort it based on the timeOfArrival key, like the following example:

my_dict = {"user": [2,3,1,4 ], "sex": ['F', 'O', 'M', 'F' ],"timeOfArrival": [4, 1, 3, 8]}

Right now I'm having trouble of thinking a straight-forward solution.

What I've tried is sorting the timeOfArrival and after that I tried looping inside my_dict so I can rearrange the values to their 'correct' positions, which works, but if I have duplicated values (i.e "timeOfArrival": [4, 4, 3, 1]}) I get a dictionary bigger than the one I gave it in the beginning.

Is there a better way to sort my dictionary?

def sortDict(dictionary={},name="test"):
  sortedList=sorted(my_dict[name])
  dictKeys=list(dictionary.keys())
  testDict={}
  for i in dictKeys:
    testDict[i]=[]
  for key in dictKeys:
    for item in sortedList:
      for pos in range(0,len(dictionary[name])):
        if(item==dictionary[name][pos]):
          testDict[key].append(dictionary[key][pos])
  return testDict
Ka_Papa
  • 137
  • 9
  • 1
    Does this answer your question? [Sorting list based on values from another list](https://stackoverflow.com/questions/6618515/sorting-list-based-on-values-from-another-list) – Maurice Meyer Mar 19 '21 at 14:14
  • 1
    This question has nothing to do with sorting dictionaries. It's about sorting and synchronizing multiple lists. – jarmod Mar 19 '21 at 14:14
  • @jarmod clearly I didn't explain my issue properly. I don't need to sort multiple lists, I need to sort a dictionary based on one of the lists. Synchronizing takes more time than repositioning – Ka_Papa Mar 19 '21 at 14:22
  • @MauriceMeyer I'll try to implement it and comeback to you to share the results – Ka_Papa Mar 19 '21 at 14:26
  • @MauriceMeyer it works, thank you. – Ka_Papa Mar 19 '21 at 14:43
  • Should the expected output sort the timeOfArrival list? Your expected output shows the timeOfArrival list does not change. – jisrael18 Mar 19 '21 at 14:47
  • You appear to be sorting lists (that happen to be referenced as values in a dict). In your example desired output, you have sorted both `my_dict["user"]` and `mydict["sex"]`, for example. They are both lists. You're using a custom sort, based on values in another list: `my_dict["timeOfArrival"]`. – jarmod Mar 19 '21 at 15:06

5 Answers5

2

I think this is what you're looking for. It determines the sort order by getting the indices of the sorted arrival times. I then uses the index order to sort all of the lists in the dict.

order = [i for i, _ in sorted(enumerate(my_dict['timeOfArrival']), key=lambda x: x[1])]
for key, value in my_dict.items():
    if key != 'timeOfArrival': # Expected output shows timeOfArrival should not be sorted
        my_dict[key] = [value[i] for i in order]
jisrael18
  • 719
  • 3
  • 10
0

You need to zip then sort:

# your unsorted dictionary
my_dict = {"user": [1, 2, 3, 4], "sex": ['M', 'F', 'O', 'F'],"timeOfArrival": [4, 1, 3, 8]}

# your sorted dictionary
sorted_dict = {}

# zip lists, sort by timeOfArrival and unpack into the new dictionary
sorted_dict["user"], sorted_dict["sex"], sorted_dict["timeOfArrival"] = zip(*sorted(zip(my_dict["timeOfArrival"], my_dict["user"], my_dict["sex"])))

# convert the tuples in the new dictionary into a list
sorted_dict["user"] = list(sorted_dict["user"])
sorted_dict["sex"] = list(sorted_dict["sex"])
sorted_dict["timeOfArrival"] = list(sorted_dict["timeOfArrival"])

# you're done ;-)
print(sorted_dict)
# {'user': [1, 3, 4, 8], 'sex': [2, 3, 1, 4], 'timeOfArrival': ['F', 'O', 'M', 'F']}

Then just reconstruct your dictionary with these newly sorted lists.

Johnny John Boy
  • 3,009
  • 5
  • 26
  • 50
  • I gave an example. The idea is solid, but I need to find a way to sort the dict without changing my answer. – Ka_Papa Mar 19 '21 at 14:29
0

The data can be merged with zip.

my_dict = {
    "user": [1, 2, 3, 4],
    "sex": ['M', 'F', 'O', 'F'],
    "timeOfArrival": [4, 1, 3, 8]}

print(list(zip(my_dict['timeOfArrival'], my_dict['user'], my_dict['sex'])))

This will give you

[(4, 1, 'M'), (1, 2, 'F'), (3, 3, 'O'), (8, 4, 'F')]

This can be sorted.

data = list(sorted(zip(my_dict['timeOfArrival'], my_dict['user'], my_dict['sex'])))
print(data)

Result:

[(1, 2, 'F'), (3, 3, 'O'), (4, 1, 'M'), (8, 4, 'F')]

Unpack the sorted data:

data = list(zip(*data))

Now data looks like this:

[(1, 3, 4, 8), (2, 3, 1, 4), ('F', 'O', 'M', 'F')]

Finally the sorted data must be put back to the matching dictionary entry

my_dict['user'] = list(data[1])
my_dict['sex'] = list(data[2])

Now my_dictcontains {'user': [2, 3, 1, 4], 'sex': ['F', 'O', 'M', 'F'], 'timeOfArrival': [4, 1, 3, 8]}.


Compressed version

my_dict = {
    "user": [1, 2, 3, 4],
    "sex": ['M', 'F', 'O', 'F'],
    "timeOfArrival": [4, 1, 3, 8]}

data = list(zip(*sorted(zip(my_dict['timeOfArrival'], my_dict['user'], my_dict['sex']))))
my_dict['user'] = list(data[1])
my_dict['sex'] = list(data[2])
Matthias
  • 12,873
  • 6
  • 42
  • 48
0

I suggest you to use "Insertion Sort" algorithm.

I modified it to fit into your example, it seeems to perform as you wish:


my_dict = {"user": [2,3,1,4 ], "sex": ['F', 'O', 'M', 'F' ],"timeOfArrival": [4, 1, 3, 8]}

def insertion_sort(my_dict):
    for k in range(1, len(my_dict['timeOfArrival'])):

        cur_timeOfArrival = my_dict['timeOfArrival'][k]
        cur_sex = my_dict['sex'][k]
        cur_user = my_dict['user'][k]
        j=k

        while j > 0 and my_dict['timeOfArrival'][j-1] > cur_timeOfArrival:
            my_dict['timeOfArrival'][j] = my_dict['timeOfArrival'][j-1]
            my_dict['sex'][j] = my_dict['sex'][j-1]
            my_dict['user'][j] = my_dict['user'][j-1]
            j -= 1

        my_dict['timeOfArrival'][j] = cur_timeOfArrival
        my_dict['sex'][j] = cur_sex
        my_dict['user'][j] = cur_user

    return my_dict

print(insertion_sort(my_dict))
#{'user': [3, 1, 2, 4], 'sex': ['O', 'M', 'F', 'F'], 'timeOfArrival': [1, 3, 4, 8]}

Regards.

caiquemmf
  • 16
  • 3
0

Thing is that I just needed to sort my dictionary and to keep my lists separate from one another, so combining the lists like so:

[(4, 1, 'M'), (1, 2, 'F'), (3, 3, 'O'), (8, 4, 'F')]

was out of the question.

Thank you all for your time and more importantly, thanks to @MauriceMeyer I got it working.

def sortDict(dictionary={},name="test"):
  sortedList=sorted(my_dict[name])
  dictKeys=list(dictionary.keys())
  testDict={}
  for key in dictKeys:
    testDict[key]=[x for _,x in sorted(zip(my_dict[name],my_dict[key]))]
  return testDict
Ka_Papa
  • 137
  • 9