Javascript 将对象数组随机拆分为两个相等的数组

Javascript 将对象数组随机拆分为两个相等的数组,javascript,arrays,Javascript,Arrays,我有这个物体阵列 let persons = [ {id: 1, name: "..."}, {id: 2, name: "..."}, {id: 3, name: "..."}, {id: 4, name: "..."}, {id: 5, name: "..."}, {id: 6, name: "..."}, {id: 7, name: "..."}, {id: 8, name: "..."} ] 我想把这个数组分成两个长度相等

我有这个物体阵列

let persons = [
    {id: 1, name: "..."},
    {id: 2, name: "..."},
    {id: 3, name: "..."},
    {id: 4, name: "..."},
    {id: 5, name: "..."},
    {id: 6, name: "..."},
    {id: 7, name: "..."},
    {id: 8, name: "..."}
]
我想把这个数组分成两个长度相等的数组。每次执行分割数组的函数时,它都应返回每个数组中的随机数据,而不是相同的对象列表

我尝试使用这个函数

function splitArr(data, part) {
    let list1 = [];
    let list2 = [];
    for(let i = 0; i < data.length ; i++) {
        let random = Math.floor(Math.random() * data.length);
        if(random % 2 === 0) {
            list1.push(data[i]);
        } else {
            list2.push(data[i]);
        }

    }
    return [list1, list2];
}
函数拆分器(数据,部件){
让list1=[];
让list2=[];
for(设i=0;i
函数每次返回的数组长度是否完全相等并不明显。有时它返回2和6元素不相等的数组


如果您只想将其分成两部分,可以使用

它需要两个参数,如果要替换元素,则需要三个参数,第一个参数是起始拼接索引。第二个是要删除的元素数。函数将返回移除的元素,将数组一分为二。由于拼接函数正在从原始数组中删除元素,因此将留下两个长度相等的数组(如果元素数为偶数)

至于你的数组的随机性,你可以在分割它之前简单地洗牌它。这是我用过的

/**
* https://stackoverflow.com/a/6274381/5784924
*洗牌阵法就位。ES6版本
*@param{Array}a items包含这些项的数组。
*/
函数洗牌(a){
对于(设i=a.length-1;i>0;i--){
常数j=数学楼层(数学随机()*(i+1));
[a[i],a[j]=[a[j],a[i]];
}
返回a;
}
让人洗牌([
{id:1,名称:“…”},
{id:2,名称:“…”},
{id:3,名称:“…”},
{id:4,名称:“…”},
{id:5,名称:“…”},
{id:6,名称:“…”},
{id:7,名称:“…”},
{id:8,名称:“…”}
]);
设firstArray=persons.splice(0,persons.length/2);

log(firstArray.map((item)=>item.id),persons.map((item)=>item.id))只需随机洗牌数组,然后将数组对半拼接即可

要洗牌数组,请使用提供的解决方案

要从中获取两个列表,请执行以下操作:

let list2 = shuffle([...data]); // spread to avoid mutating the original
let list1 = list2.splice(0, data.length >> 1); 

移位运算符
>
用于获取数组长度的截断一半。

这种方法的问题是:

if(random % 2 === 0) {
    list1.push(data[i]);
} else {
    list2.push(data[i]);
}
您正在尝试插入一个随机数组,但如果该数组的长度与另一个数组的长度相同,则无法处理(这将很难做到,您将失去随机意图)

对于每次迭代,最好在每个数组中插入随机项

let persons=[
{id:1,名称:“…”},
{id:2,名称:“…”},
{id:3,名称:“…”},
{id:4,名称:“…”},
{id:5,名称:“…”},
{id:6,名称:“…”},
{id:7,名称:“…”},
{id:8,名称:“…”}
]
功能拆分器(数据,部件){
让list1=[];
让list2=[];
让isPair=false;
而(data.length>0){
const randomEntry=Math.floor(Math.random()*data.length);
const arrayToPush=isPair?列表1:list2;
arrayToPush.push(数据[随机输入]);
数据拼接(随机输入,1);
isPair=!isPair;
}
console.log(list1.length,list2.length)
返回[list1,list2];
}

splitArr(persons)
我认为在这种情况下使用本机数组方法最快、更可靠。 我建议采用以下方法:

function splitArr(data) {
  const arrLength = data.length;

  const firstArr = data.slice(0, arrLength/2);
  const secArr = data.slice(arrLength / 2, arrLength);

  return [firstArr, secArr];
}
这样就得到了一个通用函数,它总是返回两个长度相同的数组。 您可以在边缘情况下使用
Math.min()
Math.ceil
进行实验(例如使用长度不均匀的数组)。

这对您有帮助吗

函数拆分器(数据、计数组){
data=data.slice()
常数组=[]
设i=0
while(data.length){
如果(!Array.isArray(decks[i])decks[i]=[]
数据组[i].push(data.splice(Math.random()*data.length,1)[0])
i=(i+1)%count\u
}
返回甲板
}
splitArr(人,2)//这里2个甲板2个
您可以非常轻松地使用
randoSequence
功能来实现这一点,该功能不会影响原始阵列。然后,使用函数拆分数组,并使用来处理奇数长度的原始数组

函数shuffleAndSplit(arr){
var shuffled=随机序列(arr);
shuffled.forEach((item,i)=>{shuffled[i]=item.value;});
return[shuffled.slice(0,shuffled.length>>1),shuffled.slice(shuffled.length>>1)];
}
日志(shuffleAndSplit([“a”、“b”、“c”、“d”、“e”、“f”、“g”))

对于这样一个小的数据集,
Math.random
不会一直按您想要的方式分割它。为什么需要将拆分为“随机”?不,这只是从数组中检索随机元素,并使用与我在函数
Math.floor
Math.random
中使用的方法大致相同的方法,就像我在代码中所做的那样,但它不会拆分数组,因为我正在处理react应用程序,我有和上面的对象数组,我想把这个数组分成两个数组,每次根组件挂载时,数组的两个列表必须有随机数据。每次都不一样使用trincot的解决方案。你忘记了问题的随机部分。谢谢trincot,这项工作,关于移位运算符的问题,我不能很好地理解它是如何精确工作的。它给出的结果与
Math.floor(data.length/2)
相同。这只是为了处理长度奇数的情况。如果您完全确定它是偶数,那么您可以执行
data.length/2
function splitArr(data) {
  const arrLength = data.length;

  const firstArr = data.slice(0, arrLength/2);
  const secArr = data.slice(arrLength / 2, arrLength);

  return [firstArr, secArr];
}