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