提问人:Piotr Wasilewicz 提问时间:10/7/2022 最后编辑:Piotr Wasilewicz 更新时间:10/8/2022 访问量:92
如何对列表和整数列表进行大范围排序?
How to sort liberally-deep list of lists and integers?
问:
假设我有一个这样的列表:
[[5, [2, 1], 3], [3, [8, 7], [2, 1, 3], 2], [[3, 2, 1], 3, -1]]
(每个列表可以以任何顺序存储未指定数量的整数和列表)。 排序规则:
- 整数(如果有)应位于任何列表之前
- 整数按正常排序(从小值到高值)
- 当第一个元素较低时,列表比另一个元素“小”,如果相同,则考虑第二个元素、第三个元素,依此类推。
- 如果列表的值与另一个列表的值相同但更少,则该列表较小。
[1, 2] < [1, 2, 3]
所以最终结果应该是:
[[-1, 3, [1, 2, 3]], [2, 3, [1, 2, 3], [7, 8]], [3, 5, [1, 2]], ]
如何实现这种排序?我尝试将递归函数作为键传递,但大多以 TypeError(不支持 和 )结尾。sort
sorted
<
int
list
另一个例子:
[1, 4, 3, [[5, 7, 1, 2], 2, 5, 10, 2], 8, [2, 5, [5, 3, 3]], [2, 5, 10, 2, [1, 2, 5]]]
排序后:
[1, 3, 4, 8, [2, 2, 5, 10, [1, 2, 5]], [2, 2, 5, 10, [1, 2, 5, 7]], [2, 5, [3, 3, 5]]]
答:
1赞
Marek
10/7/2022
#1
快速草稿:
def big_brain_sort(li: list) -> list:
list_with_int = []
list_with_list = []
for el in li:
if isinstance(el, int):
list_with_int.append(el)
elif isinstance(el, list):
list_with_list.append(big_brain_sort(el))
sorted_list_int = sorted(list_with_int)
for lista in sorted(list_with_list, key=lambda x: (big_brain_sort(x), len(x))):
sorted_list_int.append(lista)
return sorted_list_int
评论
0赞
Piotr Wasilewicz
10/7/2022
欢迎使用 stackoverflow。似乎代码可以满足我的需要。带有元组的不错“技巧”。lambda
0赞
Piotr Wasilewicz
10/7/2022
但是,您应该修复缩进。
0赞
Kelly Bundy
10/7/2022
@PiotrWasilewicz 我不认为 lambda 很好。如果我没记错的话,该键功能除了浪费时间(可能很多)之外没有任何效果。简化版。
1赞
Kelly Bundy
10/7/2022
@PiotrWasilewicz 我并不是说它不起作用。我是说它做了毫无意义的重复工作。
1赞
Piotr Wasilewicz
10/7/2022
它不起作用[[1, 2], [1, [2]]]
2赞
Kelly Bundy
10/7/2022
#2
正确、安全、高效地比较同级结构(即,在同一列表中深度嵌套的值)的一种方法是装饰所有内容并保持装饰状态,直到所有排序完成。然后在最后取消所有东西。这不会修改给定的结构,而是构建一个排序的新结构:
def deepsorted(x):
def decosorted(x):
if isinstance(x, int):
return 0, x
return 1, sorted(map(decosorted, x))
def undecorated(x):
islist, x = x
if islist:
return list(map(undecorated, x))
return x
return undecorated(decosorted(x))
另一种方法是不依赖自然比较,而是使用旧式函数。这就地排序:cmp
from functools import cmp_to_key
def deepsort(x):
def cmp(a, b):
if isinstance(a, int):
if isinstance(b, int):
return a - b
return -1
if isinstance(b, int):
return 1
diffs = filter(None, map(cmp, a, b))
return next(diffs, len(a) - len(b))
key = cmp_to_key(cmp)
def sort(x):
if isinstance(x, list):
for y in x:
sort(y)
x.sort(key=key)
sort(x)
测试代码(在线试用!
from copy import deepcopy
tests = [
([[5, [2, 1], 3], [3, [8, 7], [2, 1, 3], 2], [[3, 2, 1], 3, -1]],
[[-1, 3, [1, 2, 3]], [2, 3, [1, 2, 3], [7, 8]], [3, 5, [1, 2]], ]),
([1, 4, 3, [[5, 7, 1, 2], 2, 5, 10, 2], 8, [2, 5, [5, 3, 3]], [2, 5, 10, 2, [1, 2, 5]]],
[1, 3, 4, 8, [2, 2, 5, 10, [1, 2, 5]], [2, 2, 5, 10, [1, 2, 5, 7]], [2, 5, [3, 3, 5]]]),
([[1, 2], [1, [2]]],
[[1, 2], [1, [2]]]),
([[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]],
[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]),
([[[1, 2]], [[1, [2]]]],
[[[1, 2]], [[1, [2]]]]),
([[[1, [2]]], [[1, 2]]],
[[[1, 2]], [[1, [2]]]]),
([[1, 3], [1, 2]],
[[1, 2], [1, 3]]),
]
for given, wanted in tests:
copy = deepcopy(given)
deepsort(copy)
print(deepsorted(given) == wanted,
copy == wanted)
评论
0赞
Piotr Wasilewicz
10/7/2022
哇,这很短(而且可能有效)。也检查了其他情况。
0赞
Piotr Wasilewicz
10/7/2022
我正在调试这个。现在将接受马雷克版本,如果你有东西就写。
0赞
Piotr Wasilewicz
10/7/2022
在这种情况下,马雷克的解决方案也被打破了。
0赞
Kelly Bundy
10/8/2022
@PiotrWasilewicz我用两种我认为行之有效的方式代替了它。这出乎意料地棘手。
0赞
Piotr Wasilewicz
10/8/2022
是的,我想“好吧,我需要这些关系始终以相同的顺序排列,有嵌套的 ID......订购它应该很容易“,那么公司里没有人知道如何去做:)检查了我所有的案例(不多)。似乎工作得很好。
评论
3
4