J.Dawg
J.Dawg

Reputation: 47

Sorting a nested list by increasing numbers

How do you sort all the values within the nested list structure, so that the sublists are both the same length as in the original list and so that the values shift to the appropriate sublist so that they are sorted overall, not just within each sublist individually. How does one go about this??

for instance:

list1=[[0.10, 0.90, 0,20], [0.15, 0.80], [0.68, 0.08, 0.30]]

Becomes:

list1=[[0.08, 0.10, 0.15], [0.20, 0.30], [0.68, 0.80, 0.90]]

Any help is appreciated

Upvotes: 2

Views: 320

Answers (5)

RomanPerekhrest
RomanPerekhrest

Reputation: 92884

Another variation with itertools:

import itertools

list1=[[0.10, 0.90, 0.20], [0.15, 0.80], [0.68, 0.08, 0.30]]
sorted_l = sorted(itertools.chain.from_iterable(list1))
result = []
k=0
for i in (len(i) for i in list1):
    result.append(sorted_l[k:k+i])
    k=k+i

print(result)

The output:

[[0.08, 0.1, 0.15], [0.2, 0.3], [0.68, 0.8, 0.9]]

Upvotes: 0

niemmi
niemmi

Reputation: 17263

You can use chain.from_iterable to chain the lists, sort them and create an iterator. Then you can just iterate over the original lists and create a result using next:

>>> from itertools import chain
>>> l = [[0.10, 0.90, 0.20], [0.15, 0.80], [0.68, 0.08, 0.30]]
>>> it = iter(sorted(chain.from_iterable(l)))
>>> [[next(it) for _ in l2] for l2 in l]
[[0.08, 0.1, 0.15], [0.2, 0.3], [0.68, 0.8, 0.9]]

Upvotes: 2

Abdou
Abdou

Reputation: 13284

I would use itertools for this and confine the whole thing inside one function:

import itertools


def join_sort_slice(iterable):
    it = iter(sorted(itertools.chain(*iterable)))
    output = []
    for i in map(len, iterable):
        output.append(list(itertools.islice(it, i)))
    return output

Use it:

lst = [[0.10, 0.90, 0.20], [0.15, 0.80], [0.68, 0.08, 0.30]]
join_sort_slice(lst)
# [[0.08, 0.1, 0.15], [0.2, 0.3], [0.68, 0.8, 0.9]]

The idea is to chain all sublists together and then sort the outcome. This sorted output is then sliced based on the lengths of the original list of lists.

I hope this helps.

Upvotes: 1

Keith
Keith

Reputation: 645

Similar to @Evan's answer

import itertools
import numpy as np

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)

list1=[[0.10, 0.90, 0.20], [0.15, 0.80], [0.68, 0.08, 0.30]]

# get the sizes of each of the sublists and where they start
sizes = [len(l) for l in list1]
sizes.insert(0,0)
offsets = np.cumsum(sizes)

# flatten and sort
flat_list = sorted(itertools.chain(*list1))

nested = [flat_list[begin:end] for begin, end in pairwise(offsets)]
print(nested)

Upvotes: 0

Evan
Evan

Reputation: 2301

This works.

list1=[[0.10, 0.90, 0.20], [0.15, 0.80], [0.68, 0.08, 0.30]]

list_lengths = [len(x) for x in list1]
flattened = [item for items in list1 for item in items]
items_sorted = sorted(flattened)

loc = 0
lists2 = []
for length in list_lengths:
    lists2.append(items_sorted[loc:loc+length])
    loc += length

print(lists2)

You need to get list lengths at some point to build the final lists2. To get your ordered values properly, you flatten and sort the list, then you add lists to list2 by slicing your sorted items.

Note that this will work for arbitrary length lists and tuples.

Upvotes: 3

Related Questions