繁体   English   中英

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

[英]Split randomly Array of Object in two equal 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: "..."}
]

我想将此数组拆分为两个长度相等的数组。 每次执行拆分数组的函数时,它应该在每个数组中返回一个随机数据,而不是相同的对象列表。

我尝试使用此功能

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];
}

函数每次都返回完全相同长度的数组并不明显。 有时它返回 2 和 6 元素不相等的数组。

在此处输入图片说明

只需随机打乱数组,然后将数组拼接成两半。

对于改组数组,请使用此处提供的解决方案。

 function shuffle(a) { var j, x, i; for (i = a.length - 1; i > 0; i--) { j = Math.floor(Math.random() * (i + 1)); x = a[i]; a[i] = a[j]; a[j] = x; } return a; }

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

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

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

我认为在这种情况下,最快和更可靠的方法是使用本机数组方法。 我建议使用如下slice方法:

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进行试验(例如长度不均匀的数组)。

你可以做到这一点randojs.com真的很容易使用randoSequence功能,不影响原数组。 然后,使用slice函数拆分数组,并使用按位运算符>>处理奇数长度的原始数组。

 function shuffleAndSplit(arr){ var shuffled = randoSequence(arr); shuffled.forEach((item, i) => {shuffled[i] = item.value;}); return [shuffled.slice(0, shuffled.length >> 1), shuffled.slice(shuffled.length >> 1)]; } console.log(shuffleAndSplit(["a", "b", "c", "d", "e", "f", "g"]));
 <script src="https://randojs.com/1.0.0.js"></script>

如果您使用数组映射函数,这可能会更简单,但这在 Internet Explorer 中存在一些问题。 如果你不关心 IE,下面是你如何用 map 来做到这一点:

 function shuffleAndSplit(arr){ var shuffled = randoSequence(arr).map(item => item.value); return [shuffled.slice(0, shuffled.length >> 1), shuffled.slice(shuffled.length >> 1)]; } console.log(shuffleAndSplit(["a", "b", "c", "d", "e", "f", "g"]));
 <script src="https://randojs.com/1.0.0.js"></script>

如果您只想将其拆分为两个单独的部分,则可以使用splice

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

至于数组的随机性,您可以在拆分之前简单地对其进行洗牌。 在这里我使用了杰夫的回答

 /** * https://stackoverflow.com/a/6274381/5784924 * Shuffles array in place. ES6 version * @param {Array} a items An array containing the items. */ function shuffle(a) { for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; } let persons = shuffle([ {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 firstArray = persons.splice(0, persons.length / 2); console.log(firstArray.map((item) => item.id), persons.map((item) => item.id));

你的方法的问题是:

if(random % 2 === 0) {
    list1.push(data[i]);
} else {
    list2.push(data[i]);
}

您正在尝试插入一个随机数组,但是如果该数组的长度与另一个数组的长度相同,则您不会处理(这将很难做到,您将失去随机意图)

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

 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 = []; let isPair = false; while(data.length > 0){ const randomEntry = Math.floor(Math.random() * data.length); const arrayToPush = isPair?list1:list2; arrayToPush.push(data[randomEntry]); data.splice(randomEntry, 1); isPair = !isPair; } console.log(list1.length, list2.length) return [list1, list2]; } splitArr(persons)

这对你有帮助吗?

    function splitArr(data, count_decks) {
      data = data.slice()
      const decks = []
      let i = 0
      while (data.length) {
        if (!Array.isArray(decks[i])) decks[i] = []
        decks[i].push(data.splice(Math.random()*data.length, 1)[0])
        i = (i+1) % count_decks
      }
      return decks
    }

    splitArr(persons, 2) // here 2 for 2 decks

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM