Ruby 在每个位置比较2个阵列
因此,我试图完成的是编写一个(较短的)条件,以确保每个元素与其他数组不同。这是令人困惑的,但我希望这个例子能澄清这一点Ruby 在每个位置比较2个阵列,ruby,Ruby,因此,我试图完成的是编写一个(较短的)条件,以确保每个元素与其他数组不同。这是令人困惑的,但我希望这个例子能澄清这一点 array = [1, 2, 3] new_array = array.shuffle until array[0] != new_array[0] && array[1] != new_array[1] && array[2] != new_array[2] new_array = array.shuffle end
array = [1, 2, 3]
new_array = array.shuffle
until array[0] != new_array[0] &&
array[1] != new_array[1] &&
array[2] != new_array[2]
new_array = array.shuffle
end
所以我要做的是确保每个元素/索引对在另一个数组中不匹配
# [1, 2, 3] => [3, 1, 2] yayyyy
# [1, 2, 3] => [3, 2, 1] not what I want because the 2 didnt move
有没有更好的方法来做我想做的事?我查过了,有吗?没有?但我似乎不知道如何实施它们。谢谢 这里有一种可能性:
until array.zip(new_array).reject{ |x, y| x == y }.size == array.size
new_array = array.shuffle
end
但是请注意,对于
[1]
或[1,1,1,2,3]
之类的数组,当1
的实例数超过数组大小的一半时,它将中断。建议使用Array#uniq
或类似方法,同时检查大小为0
或1
的数组,具体取决于您的输入的可信度 这里有一种可能性:
until array.zip(new_array).reject{ |x, y| x == y }.size == array.size
new_array = array.shuffle
end
但是请注意,对于[1]
或[1,1,1,2,3]
之类的数组,当1
的实例数超过数组大小的一半时,它将中断。建议使用Array#uniq
或类似方法,同时检查大小为0
或1
的数组,具体取决于您的输入的可信度 我会这样做:
array.zip(new_array).all? { |left, right| left != right }
我会这样做:
array.zip(new_array).all? { |left, right| left != right }
以下两种方法在获得有效样本之前不涉及重复采样: 来自有效排列总体的样本 构建要从中采样的总体:
array = [1, 2, 3, 4]
population = array.permutation(array.size).reject do |a|
a.zip(array).any? { |e,f| e==f }
end
#=> [[2, 1, 4, 3], [2, 3, 4, 1], [2, 4, 1, 3], [3, 1, 4, 2], [3, 4, 1, 2],
# [3, 4, 2, 1], [4, 1, 2, 3], [4, 3, 1, 2], [4, 3, 2, 1]]
然后随便选一个:
10.times { p population.sample }
# [4, 3, 1, 2]
# [3, 4, 1, 2]
# [3, 4, 1, 2]
# [4, 3, 1, 2]
# [2, 1, 4, 3]
# [2, 1, 4, 3]
# [4, 1, 2, 3]
# [2, 1, 4, 3]
# [4, 3, 1, 2]
# [3, 4, 1, 2]
阵列中每个位置的顺序采样
def sample_no_match(array)
a = array.each_index.to_a.shuffle
last_ndx = a[-1]
a.dup.map do |i|
if a.size == 2 && a[-1] == last_ndx
select = a[-1]
else
select = (a-[i]).sample
end
a.delete(select)
array[select]
end
end
10.times.each { p sample_no_match(array) }
# [2, 4, 3, 1]
# [4, 3, 1, 2]
# [2, 1, 3, 4]
# [1, 3, 4, 2]
# [1, 3, 2, 4]
# [1, 3, 2, 4]
# [1, 4, 3, 2]
# [3, 4, 2, 1]
# [1, 3, 4, 2]
# [1, 3, 4, 2]
我无法证明或反驳第二种方法会产生随机样本。然而,我们可以确定结果的相对频率:
n = 500_000
h = n.times.with_object(Hash.new(0)) { |_,h| h[sample_no_match(array)] += 1 }
h.keys.each { |k| h[k] = (h[k]/(n.to_f)).round(4) }
h #=> {[1, 2, 3, 4]=>0.0418, [2, 1, 3, 4]=>0.0414, [1, 4, 2, 3]=>0.0418,
# [3, 4, 2, 1]=>0.0417, [4, 3, 2, 1]=>0.0415, [3, 1, 4, 2]=>0.0419,
# [2, 3, 1, 4]=>0.0420, [4, 2, 3, 1]=>0.0417, [3, 2, 1, 4]=>0.0413,
# [4, 2, 1, 3]=>0.0417, [2, 1, 4, 3]=>0.0419, [1, 3, 2, 4]=>0.0415,
# [1, 2, 4, 3]=>0.0418, [1, 3, 4, 2]=>0.0417, [2, 4, 1, 3]=>0.0414,
# [3, 4, 1, 2]=>0.0412, [1, 4, 3, 2]=>0.0423, [4, 1, 3, 2]=>0.0411,
# [3, 2, 4, 1]=>0.0411, [2, 4, 3, 1]=>0.0418, [3, 1, 2, 4]=>0.0419,
# [4, 3, 1, 2]=>0.0412, [4, 1, 2, 3]=>0.0421, [2, 3, 4, 1]=>0.0421}
avg = (h.values.reduce(:+)/h.size.to_f).round(4)
#=> 0.0417
mn, mx = h.values.minmax
#=> [0.0411, 0.0423]
([avg-mn,mx-avg].max/avg).round(6)
#=> 0.014388
这意味着与平均值的最大偏差仅为平均值的1.4%
这表明第二种方法是产生伪随机样本的合理方法
最初,该方法的第一行是:
a = array.each_index.to_a
然而,通过观察结果的频率分布,很明显该方法不会产生伪随机样本;因此,需要洗牌
a
这里有两种方法,在获得有效样本之前不涉及重复采样:
来自有效排列总体的样本
构建要从中采样的总体:
array = [1, 2, 3, 4]
population = array.permutation(array.size).reject do |a|
a.zip(array).any? { |e,f| e==f }
end
#=> [[2, 1, 4, 3], [2, 3, 4, 1], [2, 4, 1, 3], [3, 1, 4, 2], [3, 4, 1, 2],
# [3, 4, 2, 1], [4, 1, 2, 3], [4, 3, 1, 2], [4, 3, 2, 1]]
然后随便选一个:
10.times { p population.sample }
# [4, 3, 1, 2]
# [3, 4, 1, 2]
# [3, 4, 1, 2]
# [4, 3, 1, 2]
# [2, 1, 4, 3]
# [2, 1, 4, 3]
# [4, 1, 2, 3]
# [2, 1, 4, 3]
# [4, 3, 1, 2]
# [3, 4, 1, 2]
阵列中每个位置的顺序采样
def sample_no_match(array)
a = array.each_index.to_a.shuffle
last_ndx = a[-1]
a.dup.map do |i|
if a.size == 2 && a[-1] == last_ndx
select = a[-1]
else
select = (a-[i]).sample
end
a.delete(select)
array[select]
end
end
10.times.each { p sample_no_match(array) }
# [2, 4, 3, 1]
# [4, 3, 1, 2]
# [2, 1, 3, 4]
# [1, 3, 4, 2]
# [1, 3, 2, 4]
# [1, 3, 2, 4]
# [1, 4, 3, 2]
# [3, 4, 2, 1]
# [1, 3, 4, 2]
# [1, 3, 4, 2]
我无法证明或反驳第二种方法会产生随机样本。然而,我们可以确定结果的相对频率:
n = 500_000
h = n.times.with_object(Hash.new(0)) { |_,h| h[sample_no_match(array)] += 1 }
h.keys.each { |k| h[k] = (h[k]/(n.to_f)).round(4) }
h #=> {[1, 2, 3, 4]=>0.0418, [2, 1, 3, 4]=>0.0414, [1, 4, 2, 3]=>0.0418,
# [3, 4, 2, 1]=>0.0417, [4, 3, 2, 1]=>0.0415, [3, 1, 4, 2]=>0.0419,
# [2, 3, 1, 4]=>0.0420, [4, 2, 3, 1]=>0.0417, [3, 2, 1, 4]=>0.0413,
# [4, 2, 1, 3]=>0.0417, [2, 1, 4, 3]=>0.0419, [1, 3, 2, 4]=>0.0415,
# [1, 2, 4, 3]=>0.0418, [1, 3, 4, 2]=>0.0417, [2, 4, 1, 3]=>0.0414,
# [3, 4, 1, 2]=>0.0412, [1, 4, 3, 2]=>0.0423, [4, 1, 3, 2]=>0.0411,
# [3, 2, 4, 1]=>0.0411, [2, 4, 3, 1]=>0.0418, [3, 1, 2, 4]=>0.0419,
# [4, 3, 1, 2]=>0.0412, [4, 1, 2, 3]=>0.0421, [2, 3, 4, 1]=>0.0421}
avg = (h.values.reduce(:+)/h.size.to_f).round(4)
#=> 0.0417
mn, mx = h.values.minmax
#=> [0.0411, 0.0423]
([avg-mn,mx-avg].max/avg).round(6)
#=> 0.014388
这意味着与平均值的最大偏差仅为平均值的1.4%
这表明第二种方法是产生伪随机样本的合理方法
最初,该方法的第一行是:
a = array.each_index.to_a
然而,通过观察结果的频率分布,很明显该方法不会产生伪随机样本;因此,洗牌
a
的需要可以array
包含重复的数组?总共可以有多少个数组?假设两个数组没有重复。同样,这只适合我,这样我可以改进重构。我只是不满足于这看起来有多“平庸”。数组是否可以包含重复项?总共可以包含多少个数组?假设两个数组没有重复项。同样,这只适合我,这样我可以改进重构。我只是不满足于这看起来多么“平庸”。很好,我只是在看Array#permutation
并思考应用程序!很好,我只是在看Array#permutation
并思考应用程序!为了理解这里的过程,zip
方法允许我同时访问两个数组。然后,all?
将数组中的每个元素与其在另一个数组中的各自索引进行比较。本质上是:array.zip(新的数组)?{| el,new|el | el!=new|el}
为了让我理解这里的过程,zip
方法允许我同时访问两个数组。然后,all?
将数组中的每个元素与其在另一个数组中的各自索引进行比较。本质上是:array.zip(新的数组)?{| el,new | el!=new | el}