Python排序意外行为

huangapple go评论63阅读模式
英文:

Python Sort unexpected behaviour

问题

I understand you want a translation of the code-related portion. Here's the translation of the code without any additional information:

filtered_items = [
    (i+1, line.strip()) for i, line in enumerate(items)
    if not args.filter_string or args.filter_string.lower() in line.lower()
]

sorted_items = sorted(filtered_items, key=lambda item: (
    not item[1].startswith('('),
    item[1][:3],
    item[0],
))

If you need further assistance with this code or have any questions, please feel free to ask.

英文:

I have a data structure such that:

   [(1, '(A) Begin plans for world domination'), 
    (2, 'Listen to Symphony for the New World'), 
    (3, '(A) Change world'), 
    (4, '(D) Listen to Symphony for the New World'), 
    (5, '(C) Hello, World!'), (4, 'Improve Python todo project'), 
    (6, 'Begin plans for world domination'), 
    (7, '(A) Improve Python todo project')]

And I would like to sort first by the contents of the parentheses (if they have parentheses), and then by number.

I'm currently filtering for keywords which works fine, my sort is incorrect:

        filtered_items = [
            (i+1, line.strip()) for i, line in enumerate(items)
            if not args.filter_string or args.filter_string.lower() in line.lower()
        ]

        sorted_items = sorted(filtered_items, key=lambda item: (
            not item[1].startswith('('),
            item[1][:3],
            item[0],
        ))

this current sort will yield the output:

1 (A) Begin plans for world domination
3 (A) Change world
7 (A) Improve Python todo project
5 (C) Hello, World!'), (4, 'Improve Python todo project
4 (D) Listen to Symphony for the New World
6 Begin plans for world domination
2 Listen to Symphony for the New World

The last 2 are the wrong way round.

Can anyone explain why this is?

答案1

得分: 2

你的关键元组是(是否有括号,前三个字母,项目编号),因此当没有括号时,它根据前三个字母的字母顺序进行排序。您希望第二个元组基于括号的存在而有条件地进行排序:

sorted_items = sorted(
    filtered_items,
    key=lambda item: (not item[1].startswith("("), item[1][0:3] if item[1].startswith("(") else item[0]),
)
英文:

Your key tuple is (Whether there is parenthesis, first three letters, item number), so when there is no parenthesis, it sorts by alphabetical order based on the first three letters. You want your second tuple to be conditional based on presence of parenthesis:

sorted_items = sorted(
    filtered_items,
    key=lambda item: (not item[1].startswith("("), item[1][0:3] if item[1].startswith("(") else item[0]),
)

答案2

得分: 1

你正在使用字符串的前3个字符作为排序键的一部分,即使字符串不以括号开头。最后2个项目之所以以这种方式排序,是因为'Beg''Lis'之前。

英文:

You're using the first 3 characters of the string as part of the sort key, even if the string doesn't start with a parenthesis. The last 2 items are sorted that way because 'Beg' comes before 'Lis'.

答案3

得分: 1

你的关键元组需要有条件性。目前的构造方式是,即使没有括号,字符串的前三个字母也比数字具有更高的优先级。尝试这样做:

key=lambda item: (0, item[1][1], item[0]) if item[1].startswith("(") else (1, item[0])
英文:

Your key tuple needs to be conditional. The way it's constructed right now the first three letters of the string are higher priority than the number even if there are no parentheses. Try this:

key=lambda item: (0, item[1][1], item[0]) if item[1].startswith("(") else (1, item[0])

答案4

得分: 0

以下是已翻译好的内容:

这里有另一种方法来做这个。

但要注意括号中的值是单个大写字母

data = [
(1, '(A) 开始计划世界统治'),
(2, '听新世界交响曲'),
(3, '(A) 改变世界'),
(4, '(D) 听新世界交响曲'),
(5, '(C) 你好,世界!'),
(4, '改进Python待办项目'),
(6, '开始计划世界统治'),
(7, '(A) 改进Python待办项目')]

def k(t):
i, s = t
return ord(s[1]) if s[0] == '(' else i + ord('Z'), s

print(*sorted(data, key=k), sep='\n')

输出:

(1, '(A) 开始计划世界统治')
(3, '(A) 改变世界')
(7, '(A) 改进Python待办项目')
(5, '(C) 你好,世界!')
(4, '(D) 听新世界交响曲')
(2, '听新世界交响曲')
(4, '改进Python待办项目')
(6, '开始计划世界统治')

...根据问题描述,这是我认为输出应该看起来像的内容。

英文:

Here's another way to do this.

Caveat is that the value in parentheses is a single uppercase letter

data = [
    (1, '(A) Begin plans for world domination'), 
    (2, 'Listen to Symphony for the New World'), 
    (3, '(A) Change world'), 
    (4, '(D) Listen to Symphony for the New World'), 
    (5, '(C) Hello, World!'),
    (4, 'Improve Python todo project'), 
    (6, 'Begin plans for world domination'), 
    (7, '(A) Improve Python todo project')]

def k(t):
    i, s = t
    return ord(s[1]) if s[0] == '(' else i + ord('Z'), s

print(*sorted(data, key=k), sep='\n')

Output:

(1, '(A) Begin plans for world domination')
(3, '(A) Change world')
(7, '(A) Improve Python todo project')
(5, '(C) Hello, World!')
(4, '(D) Listen to Symphony for the New World')
(2, 'Listen to Symphony for the New World')
(4, 'Improve Python todo project')
(6, 'Begin plans for world domination')

...which, based on the description in the question, is what I believe the output should look like

huangapple
  • 本文由 发表于 2023年5月17日 22:13:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76273069.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定