频率排序问题 python - sorted() 没有给出我所期望的
frequency sorting problem python - sorted() does not give what I would expect
我有这样的代码:
def frequency_sorting(numbers):
return sorted(numbers, key=lambda i:numbers.count(i),reverse=True)
或者:
def frequency_sorting(numbers):
return sorted(numbers, key=numbers.count,reverse=True)
当我打电话时:
frequency_sorting([3,4,11,13,11,4,4,7,3])
都给我:
[4, 4, 4, 3, 11, 11, 3, 13, 7]
我预计:
[4, 4, 4, 3, 3, 11, 11, 13, 7]
我知道如何解决最初的想法。我只需要从理论上理解为什么我的代码不起作用。
您的代码不起作用,因为 11 和 3(在您的示例中)具有相同的计数;相同的排序优先级。
所以 3, 11
是一个有序序列,就像 11, 3
或 3, 3, 11, 11
或 3, 11, 3, 11
一样都是正确的,选择取决于算法的实现方式。
所以你需要指定顺序的关键不仅仅是相等元素的数量,而是相等元素的数量(重要性更高)和元素本身(如果你想要这个)。因此,如果您想要相等元素数量的反向顺序和(然后)元素值的顺序,您可以使用:
sorted(numbers, key=lambda i:(-numbers.count(i),i))
或同样
sorted(numbers, key=lambda i:(numbers.count(i),-i),reverse=True)
您可能希望按元素数量和(然后)元素的首次出现顺序排列,在这种情况下,您可以使用:
sorted(numbers, key=lambda i:(-numbers.count(i),numbers.index(i)))
或者你可以用别的东西;这取决于你想如何对具有相同计数但不同值的元素进行排序
排序是guaranteed to be stable,就是说如果有些项目有相同的键值,则保留它们原来的顺序。
更容易看到字符串发生了什么并且没有倒序:
list(sorted(['zzz', 'aa', 'cc', 'bb', 'bbb', 'aaa'], key=len))
# ['aa', 'cc', 'bb', 'zzz', 'bbb', 'aaa']
所有长度为 2 的字符串按其原始顺序首先出现,然后是所有长度为 3 的字符串,也按其原始顺序。
在您的代码中,计数为 2 的值按此顺序依次为 3、11、11 和 3。因此,排序后它们将保持此顺序(按照您的要求反转,但看起来一样)。
如果你想按计数排序,然后按值排序(而不是按原始顺序),你必须明确说明:
def frequency_sorting(numbers):
return sorted(numbers, key=lambda i:(numbers.count(i), -i), reverse=True)
我有这样的代码:
def frequency_sorting(numbers):
return sorted(numbers, key=lambda i:numbers.count(i),reverse=True)
或者:
def frequency_sorting(numbers):
return sorted(numbers, key=numbers.count,reverse=True)
当我打电话时:
frequency_sorting([3,4,11,13,11,4,4,7,3])
都给我:
[4, 4, 4, 3, 11, 11, 3, 13, 7]
我预计:
[4, 4, 4, 3, 3, 11, 11, 13, 7]
我知道如何解决最初的想法。我只需要从理论上理解为什么我的代码不起作用。
您的代码不起作用,因为 11 和 3(在您的示例中)具有相同的计数;相同的排序优先级。
所以 3, 11
是一个有序序列,就像 11, 3
或 3, 3, 11, 11
或 3, 11, 3, 11
一样都是正确的,选择取决于算法的实现方式。
所以你需要指定顺序的关键不仅仅是相等元素的数量,而是相等元素的数量(重要性更高)和元素本身(如果你想要这个)。因此,如果您想要相等元素数量的反向顺序和(然后)元素值的顺序,您可以使用:
sorted(numbers, key=lambda i:(-numbers.count(i),i))
或同样
sorted(numbers, key=lambda i:(numbers.count(i),-i),reverse=True)
您可能希望按元素数量和(然后)元素的首次出现顺序排列,在这种情况下,您可以使用:
sorted(numbers, key=lambda i:(-numbers.count(i),numbers.index(i)))
或者你可以用别的东西;这取决于你想如何对具有相同计数但不同值的元素进行排序
排序是guaranteed to be stable,就是说如果有些项目有相同的键值,则保留它们原来的顺序。
更容易看到字符串发生了什么并且没有倒序:
list(sorted(['zzz', 'aa', 'cc', 'bb', 'bbb', 'aaa'], key=len))
# ['aa', 'cc', 'bb', 'zzz', 'bbb', 'aaa']
所有长度为 2 的字符串按其原始顺序首先出现,然后是所有长度为 3 的字符串,也按其原始顺序。
在您的代码中,计数为 2 的值按此顺序依次为 3、11、11 和 3。因此,排序后它们将保持此顺序(按照您的要求反转,但看起来一样)。
如果你想按计数排序,然后按值排序(而不是按原始顺序),你必须明确说明:
def frequency_sorting(numbers):
return sorted(numbers, key=lambda i:(numbers.count(i), -i), reverse=True)