1

I currently have a small script written which takes four lists, where, for instance, every 0'th index matches each other. I sort these lists by the first list, while the other lists are sorted in the same pattern. Like so:

Unsorted lists:

list0: 4, 2, 1, 3

list1: four, two, one, three

Sorted lists:

list0: 1, 2, 3, 4

list1: one, two, three, four

This works with the following script:

list0=IN[0]
list1=IN[1]
list2=IN[2]
list3=IN[3]

list0,list1,list2,list3 =zip(*sorted(zip(list0,list1,list2,list3)))

list0,list1,list2,list3 = (list(t) for t in zip(*sorted(zip(list0,list1,list2,list3))))


#Output:
OUT = [list0,list1,list2,list3]

I want to be able to convert this to a more general script with any number of lists. Thus, my input would be a list of lists, and they should be sorted like shown in the code above. Can you help me out?

Best regards,

Ask

Ask
  • 27
  • 6
  • 1
    If it is a list of lists, wouldn't it be better to change the title of the question to "Sorting list of lists by the first list" instead of "Sorting dictionary of lists by the first list"? dictionaries are unordered by default, to me it wouldn't make sense to speak about a first element in a dictionary, as it is not guaranteed the order to be kept in the time. – Ivan De Paz Centeno Jan 10 '19 at 12:11

2 Answers2

1

Is this what you are looking for?

def sort_lists(*args):
    zipped_list = zip(*sorted(zip(*args)))
    return [list(l) for l in zipped_list]

Example:

>>> l1 = [4,2,1,3]
>>> l2 = ["four", "two", "one", "three"]
>>> sort_lists(l1, l2)
[[1, 2, 3, 4], ['one', 'two', 'three', 'four']]

Based on your code example, you could use it as follows:

>>> OUT = sort_lists(*IN)
Ivan De Paz Centeno
  • 3,595
  • 1
  • 18
  • 20
  • Your function works, but as it is written now i seemingly have to write in every input list seperately in the variable in the function. That means that as my number of input lists vary, it doesn't solve the problem *entirely*. Right now it treats a list of lists as one list and thus doesn't sort it properly. How would you make it possible to make a list of lists an input? Thanks for your time btw. – Ask Jan 10 '19 at 08:58
  • What do you mean with _"I seemengly have to write in every input list separately in the variable in the function"_ ? so far, I understand you have a list of lists, called `IN`, which is arbitrarily large (may contain N lists inside). The parameter `*args` in the function allows it to accept any number of parameters you want to append to the function. Having this scenario, you can use the star to explode the list of lists into parameters inside the function, so you don't need to write it manually. Can you please clarify the question? actually the function accepts as input a list of lists. – Ivan De Paz Centeno Jan 10 '19 at 12:05
  • Well, I'm very new to Python so I simply didn't understand that aspect of it. I can see now that that solves it, but I didn't know the abilities of the variable number of arguments (*args) function. – Ask Jan 10 '19 at 12:13
0

One more answer to the question:

list_of_lists = [
    [1, 2, 3, 0],
    [1, 2, 3, 4],
    [5, 6, 7, 8]]

dict_of_lists = {
    'a': [1, 2, 3, 0],
    'b': [1, 2, 3, 4],
    'c': [5, 6, 7, 8]}


def sort_list_of_lists(lst, idx):
    # idx - is index of list to use for sorting all the lists
    return list(list(tup) for tup in zip(*sorted(zip(*lst), key=lambda x: x[idx])))


def sort_dict_of_lists(dct, key):
    # key - is key of list to use for sorting all the lists
    keys = list(dct.keys())
    # get list from dict
    lst = [dct[key_] for key_ in keys]
    # get idx from key
    idx = keys.index(key)
    # use function 'sort_list_of_lists' for actual sorting
    return {key_: lst_ for key_, lst_ in zip(keys, sort_list_of_lists(lst, idx))}


sorted_list_of_lists = sort_list_of_lists(list_of_lists, idx=0)
sorted_dict_of_lists = sort_dict_of_lists(dict_of_lists, key='a')

If I met the problem like this I would use pandas to solve it - very convenient and efficient tool to handle tables:

import pandas as pd

dataframe_from_list = pd.DataFrame(list_of_lists).T
dataframe_from_dict = pd.DataFrame(dict_of_lists)

dataframe_from_list.sort_values(by=0, inplace=True)
dataframe_from_dict.sort_values(by='a', inplace=True)
  • I'd like to get into Panda. Do you recommend any way of getting into that? I remember you answering a question of mine a while back about indice-specific sorting: https://stackoverflow.com/a/53596807/10722189 How would you apply this to that list sorting? I'm trying to apply the list-of-lists method to that code. – Ask Jan 10 '19 at 13:34
  • @Ask In `that` case you have `IN` which is list of lists I guess. You may simply use `list_of_sorted_lists = sort_list_of_lists(IN[:4], idx=0)`. If sorting is complicated then the whole situation becomes complicated. You may improve sorting key definition inside function `sort_list_of_lists`, for example, `key=lambda x: key_second(x[idx])`. In this case you also should add another sorting step with `key_first` inside function `sort_list_of_lists`. –  Jan 10 '19 at 13:52
  • I have written this so far: http://collabedit.com/533xy . I get an error code: Traceback (most recent call last): File "", line 32, in File "", line 28, in sort_list_of_lists File "", line 28, in File "", line 19, in key_second IndexError: index out of range: 1 . Can you see where it goes wrong? My input is a list of 9 lists, where the 0'th index is the list of titles which are used as the sorting mask. – Ask Jan 11 '19 at 09:24
  • @Ask In the current version `idx` is defined and used inside function `sort_list_of_lists` so function `key_second` gets a single element (string, I guess) not tuple. So inside function `key_second` use `string` instead of `string[0]`. The same is applied to the function `key_first`. –  Jan 11 '19 at 09:48
  • Makes sense. I corrected it and it gives me the exact same error code. I've sent more information on the code sharer. – Ask Jan 11 '19 at 09:58