Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.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
';奇异的';python中的集合排序_Python - Fatal编程技术网

';奇异的';python中的集合排序

';奇异的';python中的集合排序,python,Python,当我将Python 3.8.0列表转换为一个集合时,得到的集合排序*以一种非常简单的方式进行了高度结构化。如何从伪随机列表中提取此结构 作为我正在进行的实验的一部分,我正在生成一个随机集。我惊讶地发现,绘制集合突然显示集合中意外的线性结构。所以有两件事让我困惑-为什么转换成一个集合结果会有一个顺序*最终会突出这个结构;在较小程度上,为什么伪随机集具有这种“隐藏”结构 守则: X=[randrange(250)表示范围(30)中的i] 打印(X) 打印(套(X)) 例如,哪种输出 [238、2

当我将Python 3.8.0列表转换为一个集合时,得到的集合排序*以一种非常简单的方式进行了高度结构化。如何从伪随机列表中提取此结构


作为我正在进行的实验的一部分,我正在生成一个随机集。我惊讶地发现,绘制集合突然显示集合中意外的线性结构。所以有两件事让我困惑-为什么转换成一个集合结果会有一个顺序*最终会突出这个结构;在较小程度上,为什么伪随机集具有这种“隐藏”结构

守则:

X=[randrange(250)表示范围(30)中的i]
打印(X)
打印(套(X))
例如,哪种输出

[238、202、245、94、111、106、148、164、154、113、128、10196、141、69、38、106、8、40、53、160、87、85、13、38、147、204、50、162、91]
{128, 8, 10, 141, 13, 147, 148, 154, 160, 162, 164, 38, 40, 50, 53, 196, 69, 202, 204, 85, 87, 91, 94, 106, 238, 111, 113, 245}
如预期的那样,上面列表的绘图**看起来相当随机:

而绘制集合(按照输出中的顺序)显示集合中存在的结构:

在我的机器上,这种行为与上面代码中使用的250和30的值100%一致(下面有更多示例)(我使用的示例不是cherry picked-它只是我运行的最后一个示例)。调整这些值有时会导致结构略有不同(例如,三个算术级数的子集***而不是两个)

这能在其他人的机器上复制吗?当然,这种结构的存在似乎表明伪随机数的生成不是很好,但这并不能解释转换为集合在某种意义上如何“提取”这种结构。 据我所知,没有正式的保证(当从列表转换时)集合的排序是确定的(即使是确定的,也没有在后台进行复杂的排序)。这是怎么发生的


(*):我知道,集合是无序集合,但我的意思是“有序”,即在调用
print
语句时,集合以某种顺序输出,从而始终突出显示基础集合结构

(**):这些来自Wolfram Alpha。下面还有两个例子:

(***):将随机数的范围从250更改为500时,绘制两个图:


基本上,这是因为两件事:

  • Python中的集合是使用
  • 整数的散列就是整数本身
因此,整数在基础数组中出现的索引将由整数的值决定,该值是基础数组长度的模。因此,当您将整数的连续范围放入一个集合中时,整数将倾向于保持升序:

列表(设置(范围(10000))==列表(范围(10000)) 没错,这不可能是意外! 如果您没有一个连续范围中的所有数字,那么“对基础数组的长度进行模化”部分将发挥作用:

>r=范围(0,50,4)
>>>集合(r)
{0, 32, 4, 36, 8, 40, 12, 44, 16, 48, 20, 24, 28}
>>>已排序(r,键=λx:x%32)
[0, 32, 4, 36, 8, 40, 12, 44, 16, 48, 20, 24, 28]
如果您知道底层数组的长度以及添加元素的(确定性)算法,那么序列是可预测的。在本例中,数组的长度是32,因为在添加元素时它是和

除了靠近末端的一个光点(因为数字52和56不在集合中),该范围被分成两个序列
0、4、8、
32、36、40、
,这两个序列交替出现,因为作为数字值本身的散列取模32来选择数组中的索引。有碰撞,;例如,4和36等于模32,但4首先被添加到集合中,因此36以不同的索引结束

这是这个序列的图表。图表中的结构只是一个更嘈杂的版本,因为你随机生成数字,而不是从一个带步长的范围生成

交织序列的数量将取决于集合的大小与数字采样范围的长度成比例,因为这决定了范围长度“环绕”哈希表底层数组长度的多少倍。下面是一个具有三个交错序列的示例
0、6、12、
66、72、78、
36、42、48、

>设置(范围(0、90、6))
{0, 66, 36, 6, 72, 42, 12, 78, 48, 18, 84, 54, 24, 60, 30}

啊!这就解释了(而且解释得很好)!当然,图中的这种模式与集合中的底层结构无关(我们希望这种模式出现在带有随机列表的图中,如我的示例所示)。。。我只是被剧情中意想不到的模式所吸引!如何发现30是基础数组的长度?@MarkSnyder结果是32,这意味着存在冲突,但顺序与模30相同。@MarkSnyder数组将调整大小,因为如果让数组满或接近满,哈希表的性能会显著降低。