3

如何在 Python3 中对列表 通过比较排序(不懂就问)?

 3 years ago
source link: https://www.v2ex.com/t/799423
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Python

如何在 Python3 中对列表 通过比较排序(不懂就问)?

  superhxl · 2 小时 11 分钟前 · 227 次点击

已知列表和字典,列表是需排序元素,字典指明了元素间的优先关系,譬如 S1 需在 S3 之前,而 S3 又在 S2 之前。

s = ['S1','S2','S3']

val = {('S1','S3'):1,('S3','S2'):1}

希望得到的结果是['S1','S3','S2'],请问有何好的实现方式?

自己想用 python 中的 sort 的 cmp 参数进行排序,结果竟然没排序,不知原因。

from functools import cmp_to_key

 s.sort(key=cmp_to_key(lambda x,y: val.get((x,y),0)))
6 条回复    2021-09-02 12:45:43 +08:00

toaruScar

toaruScar   2 小时 1 分钟前

可以弄成一个 class,然后用 functools.total_ordering 自定义对比函数。

MoYi123

MoYi123   1 小时 58 分钟前

s = ['S1', 'S2', 'S3']
val = {('S1', 'S3'): 1, ('S3', 'S2'): 1}


class S(str):

____def __lt__(self, other):
________if (self, other) in val:
____________return val[(self, other)] == 1
________return False


s = [S(i) for i in s]
s.sort()
print([str(i) for i in s])

能用, 但是应该有更好的办法

Trim21

Trim21   1 小时 57 分钟前 via Android

key=lambda x: {s1: 1 , s3: 2, s3: 3}.get(x, 0)

lonelinsky

lonelinsky   1 小时 22 分钟前

s = ['S1','S2','S3']
val = {('S1','S3'):-1,('S3','S2'):-1} # 这里你一开始的定义有点问题,如果你希望 S1 排在 S3 前面,则它的值应该是负的

s.sort(key=cmp_to_key(lambda x,y: val.get((x,y), -val.get((y,x), 0)))) # 这里你可能需要同时处理 (y, x) 的情况,如果你的定义是对称的。即 S1 在 S3 前面 <=> S3 在 S2 后面

注意你现在的方式里面对于未出现 val 里面的对,都会当成不需要排序的对象。如果你是像解决 AOE 网络的拓扑排序问题,建议直接看相关算法。

=============================
你一开始的排序完全没用是因为排序时候,假设按序比较
(S1, S2) 你的 val 里面没有,返回 0 表示相等,不用做任何操作
(S2, S3) 你的 val 里面还是没有,返回 0 表示相等,又不用做任何操作,所以它已经排好序了

lonelinsky

lonelinsky   1 小时 14 分钟前

typo
S1 在 S3 前面 <=> S3 在 S1 后面

superhxl

superhxl   53 分钟前

@lonelinsky 我的定义没问题,也许有更好的方式。本身问题背景是若干个点,一次对这些点遍历,想要打印遍历的顺序。字典中的值表示相继访问的顺序,访问 S1 后访问 S3,访问 S3 后访问 S2.

关于 cmp 的应用再查查文档,这个确实是临时搜索的解决方案。

目前可以通过冒泡排序解决,但我想应该有更好办法。
```python
for p in range(len(s)-1):
for q in range(p + 1, len(s)):
if sol[z[(s[q],s[p])]] == 1:
s[p], s[q] = s[q], s[p]
```
@toaruScar 去学习一下具体用法。
@MoYi123 好复杂的样子。
@Trim21 没看懂。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK