Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
list.sort(key=list.count)在Python3.x中是如何工作的?_Python_Python 3.x_List_Sorting - Fatal编程技术网

list.sort(key=list.count)在Python3.x中是如何工作的?

list.sort(key=list.count)在Python3.x中是如何工作的?,python,python-3.x,list,sorting,Python,Python 3.x,List,Sorting,我想根据元素的频率对数字列表进行排序。 (我找到了几种方法。) 在我的探索过程中,我尝试了下面的例子 问题:list.sort(key=list.count)是如何工作的?是否可以在list.sort()期间使用list.count() 我了解到,在排序之前,会对列表中的每个元素计算key函数,这些值在排序期间用于比较 另外,我在某个地方读到,在sort()期间,列表有点被锁定。 (很抱歉,我现在找不到参考资料-在过去的几个小时里,我已经阅读了很多关于这个主题的博客和教程,包括Python文档和

我想根据元素的频率对数字列表进行排序。 (我找到了几种方法。)

在我的探索过程中,我尝试了下面的例子

问题:list.sort(key=list.count)是如何工作的?是否可以在list.sort()期间使用list.count()

我了解到,在排序之前,会对列表中的每个元素计算key函数,这些值在排序期间用于比较

另外,我在某个地方读到,在sort()期间,列表有点被锁定。 (很抱歉,我现在找不到参考资料-在过去的几个小时里,我已经阅读了很多关于这个主题的博客和教程,包括Python文档和如何排序)

这就是一个例子

### Python 3.7 ###

data = [22, 11, 33, 99, 88, 77, 22, 44, 55, 44, 66, 22]

# sort by value
data.sort()
print(data)
>>> [11, 22, 22, 22, 33, 44, 44, 55, 66, 77, 88, 99]

# sort by frequency, i.e. list.count()
data.sort(key=data.count)
print(data)
>>> [11, 22, 22, 22, 33, 44, 44, 55, 66, 77, 88, 99]
# expected >>> [11, 33, 55, 66, 77, 88, 99, 44, 44, 22, 22, 22]
# but no change, the value-sorted list is printed

# or
data.sort(key=lambda e: data.count(e))
print(data)
>>> [11, 22, 22, 22, 33, 44, 44, 55, 66, 77, 88, 99]
# expected >>> [11, 33, 55, 66, 77, 88, 99, 44, 44, 22, 22, 22]
# but no change, the value-sorted list is printed
注意:没有错误消息

作为补充,我想提到的是,以下工作与预期相符

max(data, key=data.count)
当然,这也给出了预期的结果

print(sorted(data, key=data.count))
>>> [11, 33, 55, 66, 77, 88, 99, 44, 44, 22, 22, 22]
根据文档,sorted()和sort()应该返回相同的结果,不是吗

谢谢你的见解

编辑: 根据文件-据我所知:

  • sort()接受key函数并向key函数提供列表中的单个成员

    ->计算结果是每个元素的出现次数(等效元素结果与等效计算结果相同,因为它们在列表中的频率相同)

    :我没有在Python中调试这么深的代码的经验

    :本身data.count()返回我检查过的频率的适当列表

  • 保存/缓存计算结果

    这是其效率

    的基础。
  • 使用缓存的计算结果(!)确定原始列表的顺序

    ->最不频繁的元素在列表的前面,最频繁的元素在后面

    !!!这是不会发生的

  • 将列表按新顺序保存到位

    。。。或者,这一切都没有发生

  • 此外,据我所知(虽然不确定),在这个过程中,sort()会将原始列表从其他使用/访问中“锁定”(并在某个地方释放锁-我记得,解释中有一些关于多线程应用程序的内容)

    重要:

    我不是在寻找解决方案或代码来对列表进行排序-我希望您能解释一下发生了什么:

    • 为什么结果是实际返回的列表而不是我的期望

    • 相比之下,为什么sorted()按预期工作


      • 这是一个有趣的问题,我没有完整的答案,因为它在这里的源代码中的某个地方:

        但是,通过使用以下功能作为键,您可以获得部分答案:

        def count(e):
           print(data)
           return data.count(e)
        
        如果这样做,您将看到它只打印“[]”。这意味着在就地排序过程中,可能是为了避免弄乱列表,列表现在指向一个空列表(即使引用本身数据没有更改)。因此data.count(e)始终等于0,并且列表保持不变

        因此,在就地排序过程中使用列表的唯一方法是复制列表,例如:

        data.sort(key=data.copy().count)
        
        我要补充的是,这不会增加复制列表整个过程的成本,因为上面的行已经是O(n²log(n))。实际上,对列表中的每个元素调用count是一个非常糟糕的主意。一种有效的O(n log(n))方法是:

        nb_occ={}
        for x in data:
            nb_occ[x]=nb_occ.get(x,0)+1
        data.sort(key=nb_occ.__getitem__)
        
        编辑:请参阅juanpa.arrivillaga的答案,这种行为实际上记录在排序方法文档中。

        好,根据:

        CPython实现细节:在对列表进行排序时 试图改变甚至检查列表的效果是 未定义Python的C实现使列表显示为空 持续时间,如果可以检测到列表 在排序过程中发生了变异


        如果是粗体部分,那么对于任何元素,
        data.count
        将返回
        0
        ,排序不会改变列表的顺序。

        @juanpa.arrivillaga我不明白背景中发生了什么-当然这不是我所怀疑的,这就是我包含实际输出和预期输出的原因。用我期望的解释来扩展问题。啊,我读得不够仔细。这很奇怪,看起来像一只虫子。另一方面,您应该注意到,这是非常低效的,它将排序算法降级为O(N^2),而不是O(N*logn)以挑剔措辞:-)实际上,排序算法实现的效率保持不变。这是元素“权重”的计算(在排序实际开始之前)——这里给出了答案中的一些其他示例,我假设开发人员在实现list.count()时也做得很好。查找源代码和/或基准测试时要了解的内容。
        list.count
        是一个O(n)操作,因此在某些列表中为x调用
        [x.count()
        就是一个O(n**2)操作。因此,它肯定会影响算法的效率。如果您不想这样做,请从集合导入计数器执行类似于
        的操作;计数=计数器(某些列表);一些_list.sort(key=counts.get)
        我同意你的观点,谢谢你的解释。我只是想更准确(可能不够准确)地将频率计算与排序分开,因为它们一个接一个地发生。请您添加并解释一下!实际上,我所做的是创建了两个列表,分别是a和s,在其中添加了数据列表成员及其频率。然后,我将这些列表(a和s)作为键值对添加到dict(p)中。现在列表没有排序,所以现在我使用了内置的排序函数来根据值对dict进行排序。感谢您的解释!这是一种有效的方法吗
        nb_occ={}
        for x in data:
            nb_occ[x]=nb_occ.get(x,0)+1
        data.sort(key=nb_occ.__getitem__)