Like I have this list and I tried many things but end up getting type error. Is it even possible in python?
Input = [3,1,0,4,1,[5,4,7]]
output = [0,1,1,3,4,[4,5,7]]
You can use itertools.groupby
:
from itertools import groupby
def sorted_mixed(lst):
output = []
for k, g in groupby(lst, key=lambda x: isinstance(x, list)):
if k: # if the group consists of lists
output += [sorted(x) for x in g] # sort each list
else: # if the group consists of others
output += sorted(g)
return output
print(sorted_mixed([3,1,0,4,1,[5,4,7]]))
# [0, 1, 1, 3, 4, [4, 5, 7]]
print(sorted_mixed([3,1,[9,4,1],4,1,[5,4]]))
# [1, 3, [1, 4, 9], 1, 4, [4, 5]]
print(sorted_mixed([[4,3],[2,1]]))
# [[3, 4], [1, 2]]
The items are sorted locally, not globally. For a different behavior more information should be given.
from itertools import groupby, chain
def local_ordering(lst): # depends on groupby & chain
return list(chain.from_iterable([sorted(next(grp))] if gr_type is list else sorted(grp) for gr_type, grp in groupby(lst, key=type)))
def global_values_local_lists_ordering(lst): # depends on itertools.groupy
# global for values, local for lists
grps = {}
only_numbers = []
# group by type
for i, (gr_type, grp) in enumerate(groupby(lst, key=type)):
if gr_type == list:
# sort nested list
grps[i] = sorted(next(grp))
else:
# add grp size
g = list(grp)
grps[i] = len(g)
only_numbers.extend(g)
# in place sort
only_numbers.sort()
# final list
out = []
for v in grps.values():
if isinstance(v, list):
out.append(v)
else:
# iterate over group of numbers
for i in range(v):
out.append(only_numbers.pop(0))
return out
def global_ordering(lst): # no imports needed
# flat the list
flat_list = []
lists_info = {}
for i, term in enumerate(lst):
if isinstance(term, list):
lists_info[i] = len(term)
flat_list.extend(term)
else:
flat_list.append(term)
# in-place sort
flat_list.sort()
# regrouping
out = []
index = 0
while flat_list:
if index in lists_info:
step = lists_info.pop(index)
out.append([flat_list.pop(0) for _ in range(step)])
else:
out.append(flat_list.pop(0))
index += 1
return out
Tests and (order) ambiguities:
Case from the question: every implementation has the same output
a = [3,1,0,4,1,[5,4,7]]
print(a)
print()
print(local_ordering(a))
print(global_values_local_lists_ordering(a))
print(global_ordering(a))
Output
[3, 1, 0, 4, 1, [5, 4, 7]]
[0, 1, 1, 3, 4, [4, 5, 7]]
[0, 1, 1, 3, 4, [4, 5, 7]]
[0, 1, 1, 3, 4, [4, 5, 7]]
With a different list with more sublists: each implementation behave differently, hence "order ambiguity"
a = [3,1, [9, 4, 1],4,1,[5,4]]
print(a)
print()
print(local_ordering(a))
print(global_values_local_lists_ordering(a))
print(global_ordering(a))
Output
[3, 1, [9, 4, 1], 4, 1, [5, 4]]
[1, 3, [1, 4, 9], 1, 4, [4, 5]]
[1, 1, [1, 4, 9], 3, 4, [4, 5]]
[1, 1, [1, 3, 4], 4, 4, [5, 9]]
You could also make use of numpy arrays and masking. I assume that you want to preserve the position of the list inside the global list but order all numbers of the global list. First create a mask that differentiates list items that are numbers from list items that are list through Booleans. Then create a sorted list with the numbers, sort each inner list and place the inner list at the right position in the global list. np.dnenumerate is like enumerate for numpy arrays.
lst = [3,1,0,4,1,[5,4,7]]
import numpy as np
arr = np.array(lst)
mask = np.array([True if type(i) != list else False for i in lst])
result = sorted(arr[mask])
for idx_lst, idx_mask in np.ndenumerate(np.where(mask==False)):
result.insert(idx_mask, sorted(arr[~mask][idx_lst[1]]))
result:
[0, 1, 1, 3, 4, [4, 5, 7]]
other example:
lst = [3,1, [9, 4, 1],4,1,[5,4]]
result:
[1, 1, [1, 4, 9], 3, 4, [4, 5]]
Hey Anshuman Sharma there are many ways to solve it, as a beginner in python I solved it like this, but there are more elegant ways with list comprehension.
Input = [3, 1, 0, 4, 1, [5, 4, 7]]
new_list = []
for value in Input:
if type(value) != list:
new_list.append(value)
else:
for element in value:
new_list.append(element)
print(f"This is the new list: {new_list}")
new_list.sort()
print(new_list)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.