Julia 我如何洗牌一系列数字,然后将其分割成一定长度的子阵列?

Julia 我如何洗牌一系列数字,然后将其分割成一定长度的子阵列?,julia,Julia,假设我有一个范围1:N,我想将该范围随机排列成一个顺序,然后将得到的乱排列数组拆分成最多为128个元素的子数组。我该怎么做 此问题基于JuliaLang slack频道上出现的一个问题。标准库中的函数shuffle可用于将容器随机排列为随机顺序: julia> using Random: shuffle julia> shuffle(1:10) 10-element Array{Int64,1}: 6 9 3 2 10 1 8 7 5 4 J

假设我有一个范围
1:N
,我想将该范围随机排列成一个顺序,然后将得到的乱排列数组拆分成最多为
128
个元素的子数组。我该怎么做


此问题基于JuliaLang slack频道上出现的一个问题。

标准库中的函数
shuffle
可用于将容器随机排列为随机顺序:

julia> using Random: shuffle

julia> shuffle(1:10)
10-element Array{Int64,1}:
  6
  9
  3
  2
 10
  1
  8
  7
  5
  4
Julia的
Base
中的函数
Iterators.partition
可用于在固定长度的块中迭代iterable:

julia> using Base.Iterators: partition

julia> partition(1:20, 7)
Base.Iterators.PartitionIterator{UnitRange{Int64}}(1:20, 7)
但是,
partition
默认返回一个惰性迭代器,因此如果我们想具体化实际结果,我们需要
收集它:

julia> collect(partition(1:20, 7))
3-element Array{UnitRange{Int64},1}:
 1:7
 8:14
 15:20
综上所述,我们有

julia> using Random: shuffle

julia> using Base.Iterators: partition

julia> shuffle_partition(N; chunk_size=128) = (collect ∘ partition)(shuffle(1:N), chunk_size)
shuffle_partition (generic function with 1 method)

julia> shuffle_partition(503)
4-element Array{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},1}:
 [313, 51, 117, 373, 381, 340, 342, 415, 423, 453  …  201, 178, 167, 242, 2, 76, 146, 439, 363, 448]
 [115, 121, 306, 440, 295, 181, 30, 280, 388, 227  …  362, 39, 317, 171, 55, 214, 261, 251, 96, 9]
 [486, 248, 161, 319, 325, 176, 80, 369, 434, 209  …  442, 350, 273, 419, 130, 305, 192, 482, 265, 234]
 [460, 31, 400, 466, 220, 447, 119, 446, 198, 141  …  226, 438, 74, 152, 203, 303, 378, 231, 458, 194]

julia> length.(ans)
4-element Array{Int64,1}:
 128
 128
 128
 119

此答案基于在Slack上找到的答案

parts = view.(Ref(shuffle(1:N)),(i:min(i+k-1, N) for i in 1:k:N))
这假设
N
是元素数,分区大小是
k
。获得的结果是一个视图列表(因此,无序1:N在内存中只存储一次)。注意如何使用
Ref
来避免无序列表上的矢量化

样本测试代码:

julia> using Random

julia> N, k = 20, 4;

julia> parts = view.(Ref(shuffle(1:N)),(i:min(i+k-1, N) for i in 1:k:N))
5-element Array{SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true},1}:
 [18, 15, 1, 6]
 [10, 20, 4, 14]
 [17, 9, 19, 16]
 [5, 8, 12, 3]
 [11, 13, 2, 7]
使用迭代器: 我认为最简单的方法是使用randperm(如果值介于1和N之间),所以


应该可以工作。

有一个专门的函数来创建置换,
randperm(n)
using Base.Iterators: partition
using Random: randperm

N = 513
k = 128

collect(partition(randperm(N), k))