繁体   English   中英

按特定元素和该元素的子字符串对元组列表进行排序

[英]Sort list of tuples by a particular element, & by a sub-string of that element

我正在尝试对元组列表进行排序。 它们的格式如下:

("First Last", 3, 0)

换句话说:

(string, int, int)

我想按字符串值(第一个元组元素)排序。 我发现了如何从这个很棒的答案中按某个元素对元组列表进行排序: https : //stackoverflow.com/a/3121985/8887398

这是我的代码:

# Yes, I do want to start from element 1 btw
myList[1:].sort(key=lambda tup: tup[0])

当我只有名字作为元组中字符串的值时,这非常有用,例如:

("George", 8, 3)

然后我添加了姓氏,例如:

("George Manning", 8, 3)

它不再正确排序,因此我尝试了以下操作:

myList[1:].sort(key=lambda tup: (tup[0].split(" ")[1]))

我非常有信心这会起作用。 没有。 我感到困惑,因为我知道我的split方法正确地从调试中提取了姓氏。 我究竟做错了什么? 如何按姓氏对列表进行排序?

这是一个例子。 是的,它们是假名字:

myList = [
    ("NAME", "SOME LABEL 1", "SOME LABEL 2"),
    ("Kevin Lee", 45, 4),
    ("John Bowes", 35, 2),
    ("George Smith", 8, 3),
    ("Gina Marnico", 40, 3),
    ("Alice Gordon", 48, 7),
    ("Lee Jackson", 49, 7),
    ("Adam Hao", 50, 4),
    ("Adrian Benco", 23, 2),
    ("Jessica Farner", 43, 20),
    ("Greg Hyde", 34, 20),
    ("Ryan Valins", 39, 7),
    ("Gary Funa", 49, 7),
    ("Sam Tuno", 15, 4),
    ("Katy Sendej", 30, 2),
    ("Jessica Randolf", 44, 8),
    ("Gina Gundo", 47, 30)
]

myList[1:].sort(key=lambda tup: (tup[0].split(" ")[1]))

我跳过第一个值,因为它是标签信息。 我希望该元素保持不变,并且列表的其余部分按姓氏排序。

如果您想按姓氏进行排序,则可以完成以下工作:

a = myList[1:]
a.sort(key=lambda tup: tup[0].split(" ")[1])
myList[1:] = a

结果:

[
    ('NAME', 'SOME LABEL 1', 'SOME LABEL 2'),
    ('Adrian Benco', 23, 2),
    ('John Bowes', 35, 2),
    ('Jessica Farner', 43, 20),
    ('Gary Funa', 49, 7),
    ('Alice Gordon', 48, 7),
    ('Gina Gundo', 47, 30),
    ('Adam Hao', 50, 4),
    ('Greg Hyde', 34, 20),
    ('Lee Jackson', 49, 7),
    ('Kevin Lee', 45, 4),
    ('Gina Marnico', 40, 3),
    ('Jessica Randolf', 44, 8),
    ('Katy Sendej', 30, 2),
    ('George Smith', 8, 3),
    ('Sam Tuno', 15, 4),
    ('Ryan Valins', 39, 7)
]

如果要按姓氏排序然后首先可以执行以下操作:

a.sort(key=lambda tup: list(reversed(tup[0].split(" "))))

删除标签行,它可以工作:

    myList.sort(key=lambda tup: (tup[0].split(" ")[1]))

结果:

    ('Adrian Benco', 23, 2) 
    ('John Bowes', 35, 2) 
    ('Jessica Farner', 43, 20) 
    ('Gary Funa', 49, 7) 
    ('Alice Gordon', 48, 7) 
    ('Gina Gundo', 47, 30) 
    ('Adam Hao', 50, 4)
    ('Greg Hyde', 34, 20) 
    ('Lee Jackson', 49, 7) 
    ('Kevin Lee', 45, 4)
    ('Gina Marnico', 40, 3)
    ('Jessica Randolf', 44, 8) 
    ('Katy Sendej', 30, 2) 
    ('George Smith', 8, 3) 
    ('Sam Tuno', 15, 4) 
    ('Ryan Valins', 39, 7)

[myList[0]] + sorted(myList[1:], key=lambda t: t[0].split(' ')[1])

您还可以选择不进行适当排序并保持标签线不变。

表达式myList[1:]创建一个单独的列表对象,其缓冲区与myList的缓冲区不同。 您已成功就地对该对象进行了排序,但是结果被丢弃而不会影响原始的myList

您有两种选择。 最简单的方法是保留已排序的对象,然后重新插入该对象,或者仅将其固定在第一个元素上:

data = myList[1:]
data.sort(key=lambda x: x[0].split()[::-1])
myList[1:] = data

要么

...
myList = [myList[0]] + data

要么

...
myList = myList[:1] + data

使用sorted ,可以使代码更加简洁,因为它具有返回值:

myList[1:] = sorted(myList[1:], key=lambda x: x[0].split()[::-1]))

要么

myList = [myList[0]] + sorted(myList[1:], key=lambda x: x[0].split()[::-1]))

要么

myList = myList[:1] + sorted(myList[1:], key=lambda x: x[0].split()[::-1]))

您甚至可以在这里使用wrap-sort-unwrap模式。 包装器将是一个标志,指示元素是否为标头,使您可以立即对整个列表进行排序,并将标头保持在原位置。 我不建议在此使用此方法,因为它比其他方法过于刻板且难以理解。 但是,您可能会发现该模式在其他地方很有用:

myList = [x[1] for x in sorted(enumerate(myList), key=lambda x: (bool(x[0]), x[1][0].split()[::-1]))]

如果您更改程序的设计以将同类数据保留在列表中,那么所有这些问题都将消失。 假设您从CSV文件中获取列表。 您始终可以执行以下操作:

myHeader, *myList = myList
myList.sort(...)

第一行是一种简单的语法糖,用于剥离第一个元素并重新包装其余元素。 它基本上等同于

myHeader, myList = myList[0], myList[1:]

在所有情况下,我建议在键中使用.split()[::-1]或至少使用.split()[-1]而不是.split(' ')[1] 如果姓氏匹配,则第一个选项将允许您按名字排序。 它依赖于词典的序列比较。 第二个选项将使用名称的最后一个元素作为排序键,使其对中间名称和单个名称具有鲁棒性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM