I have a function that sorts a list of lists by the first list. When I use the function with the variables like so:
sort_lists(IN[0],IN[1],IN[2])
it works perfectly. Although, as I don't know how many lists my input contains, I want to use this as my variable:
sort_lists(IN[idx] for idx in range(len(IN)))
Although this returns a sorting of one list (the superlist). Why is there a difference between these variables, and how can I improve the code?
Here is the function if decisive (here IN[0] is the input with a number of sublists):
def sort_lists(*args):
zipped_list= zip(*sorted(zip(*args)))
return [list(l) for l in zipped_list]
OUT = sort_lists(data_sort[0],data_sort[1],data_sort[2])
I want to use this output:
OUT = sort_lists(data_sort[idx] for idx in range(len(IN[0])))
Two things to understand here:
*args
will give you all function parameters as a tupleIN[idx] for idx in range(len(IN))
is a generator expressionYou can see how your inputs are different if you simply add print
statement in your function:
def sort_lists(*args):
print(args)
zipped_list= zip(*sorted(zip(*args)))
return [list(l) for l in zipped_list]
Let the input list of lists be: lists = [[2, 1, 3], [1, 3, 4], [5, 4, 2]]
.
sort_lists(lists[0], lists[1], lists[2])
will print: ([2, 1, 3], [1, 3, 4], [5, 4, 2])
. That's a tuple of inner lists.
Though, if you call it like this:
sort_lists(lists[idx] for idx in range(len(lists)))
or
sort_lists(sublist for sublist in lists)
this will print (<generator object <genexpr> at 0x0000007001D3FBA0>,)
, a one-element tuple of a generator.
You can make your function work with a generator by accepting only one parameter:
def sort_lists(arg):
zipped_list= zip(*sorted(zip(*arg)))
return [list(l) for l in zipped_list]
sort_lists(lists[idx] for idx in range(len(lists)))
# [[1, 2, 3], [3, 1, 4], [4, 5, 2]]
but I suggest to leave your function as is, and unpack your lists in the place where you call it instead:
>>> sort_lists(*lists)
[[1, 2, 3], [3, 1, 4], [4, 5, 2]]