问题描述
例如,给定数组:
const arr = [1,2,3,4,5,6,7,8];
例如,调用sample(arr,2)
会返回[[7,8],[4,5],[2,3]]
,调用sample(arr,4)
必然会返回[[1,4],[5,8]
,而调用sample(arr,2)
会引发错误。
编辑-也许在最初的问题中并不清楚:样本应该是连续元素的列表。例如,这就是sample(arr,4)
只能返回[[1,8]
而不能返回[[2,1,6],8]
的原因。
解决方法
您可以使用贪婪算法,并从混洗后的数组中提取m个n元组:
const arr = [2,1,3,4,5,6,7,8];
function sample(arr,length,size){
if(arr.length < length*size)
throw new Error("too short");
arr.sort(() => Math.random() - 0.5);
let res = [];
for(let i = 0; i < length; i++) res.push(arr.slice(i*size,i*size+size));
return res;
}
console.log(sample(arr,2,4));
,
您可以首先创建一个具有返回值格式的列表:
WRITE (2,'(a,9e10.3)') 'JC1 ',xk,xtd2 (j,jj),x8,jj2),cl,jj5),xkcheck,jj3),jj4)
IF (ABS (1.0 - (xk / xtd2 (j,jj))) < tolkn) THEN
IF (ABS (x8 - xtd2 (j,jj2)) < tolerance .AND. ABS (cl - xtd2 (j,jj5)) < tolerance) THEN
IF (ABS (xkcheck - xtd2 (j,jj3)) < tolerance) THEN
IF (iconcrete .EQ. INT (xtd2 (j,jj4))) jmx = j ! jmx is assigned the index of a matching material (within tolerance)
END IF
END IF
END IF
可以使用以下长度写出这些格式数组:
[ 1,8]
[<---->,<---->,<>,<>] // sample(array,2)
[<------------>,<------------>] // sample(array,4)
然后将格式数组改组以获得随机样本选择:
[1,8]
[ 2,1] // sample(array,2)
[ 4,4] // sample(array,4)
然后对于格式数组的每个元素,从输入数组中删除前[1,4)
个元素。然后存储它们,除非它是填充符(将一个大小的块放入以达到数组长度)。
n
最后将产生的样本洗牌。
[1,8]
[[1,2],[4,5],[6,7]] // sample(array,2)
[[1,4],[5,8]] // sample(array,4)
[1,8]
[[4,[1,2)
[[5,8],4]] // sample(array,4)
请注意,const arr = [1,8];
console.log(sample(arr,2));
console.log(sample(arr,4));
console.log(sample(arr,2));
function randomInt(limit) {
return Math.floor(Math.random() * limit);
}
function shuffle(array) {
for (let limit = array.length; limit > 0; --limit)
array.push(...array.splice(randomInt(limit),1));
}
function sample(array,sampleCount,sampleLength) {
let elementCount = sampleCount * sampleLength;
if (elementCount > array.length)
throw "invalid sampleCount/sampleLength arguments";
const filler = {valueOf: () => 1};
const fillerCount = array.length - elementCount;
const lengths = Array.from(
{length: sampleCount + fillerCount},(_,i) => i < sampleCount ? sampleLength : filler
);
shuffle(lengths);
const samples = Array.from(array);
for (const length of lengths) {
const sample = samples.splice(0,length);
if (length === filler) continue;
samples.push(sample);
}
shuffle(samples);
return samples;
}
在===
中很重要。如果您使用length === filler
,则==
也将等于filler
。然后,这将与诸如每个样本长度为1
的{{1}}之类的调用冲突。
sample(array,1)
,
我认为最好的实现将首先洗牌。这是我的两分钱:
function shuffle(array){
let a = array.slice(),i = a.length,n,h;
while(i){
n = Math.floor(Math.random()*i--); h = a[i]; a[i] = a[n]; a[n] = h;
}
return a;
}
function sample(array,chunks,count){
const r = [],a = shuffle(array);
for(let n=0; n<chunks; n++){
r.push(a.splice(0,count));
}
return r;
}
const arr = [1,2)); console.log(sample(arr,4));
,
您可以轻松地使用Rando.js(这是加密安全的),map和splice来完成此操作。只需使用randojs的randoSequence
函数将提供的数组改组并在改组后的数组中拼接n
size-m
数组即可获得我们需要返回的所有内容。如果所提供的数组的值太少,则我们返回的后面的数组将更短。
function sample(arr,m){
arr = randoSequence(arr).map(i => i.value),sample = [];
for(var i = 0; i < n; i++) sample[i] = arr.splice(-m);
return sample;
}
console.log(sample([1,2));
<script src="https://randojs.com/2.0.0.js"></script>