【问题标题】:How to shuffle an array of objects in javascript?如何在javascript中打乱一组对象?
【发布时间】:2018-03-29 11:48:38
【问题描述】:

下面的代码适用于普通数组,但不适用于带有对象的数组。有人知道该怎么做吗?

const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

function shuffle(array) {
  for (let i = array.length - 1; i > 0; i--) {
    let j = Math.floor(Math.random() * (i + 1));
    let temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}

const result = shuffle(array);

console.log(JSON.stringify(result));

【问题讨论】:

  • 你能详细说明一下数组的结构是什么样的吗?
  • “带对象的数组”是什么意思?
  • 此代码与数组的内容无关。将所有数字替换为对象 - { id: 1 }、{ id: 2 } 等......你可以看到它。
  • 根据我的经验,除了这种情况外,这可行:每个元素都是对象数组的关联数组。如果我将其中一个数组元素(它本身就是一个数组)传递给这个函数,那么这个数组就不会被打乱。但是,如果您修改代码以制作数组的副本,然后将其打乱并返回,那将起作用。您必须使用合法的数组复制方法,例如:newArray = [...array],换句话说,newArray = array 将不起作用。

标签: javascript arrays shuffle


【解决方案1】:

尝试像这样 sn-p 排序:

console.log( [
    { some: 1 },
    { some: 2 },
    { some: 3 },
    { some: 4 },
    { some: 5 },
    { some: 6 },
    { some: 7 },
  ]
  .sort( () => Math.random() - 0.5) );

针对 Martin Omanders 的评论:这是根据Fisher-Yates algorithm 的随机播放方法

const result = document.querySelector("pre");
for (let i=0; i<20; i+=1) {
  result.textContent += 
    JSON.stringify(shuffleFisherYates([0,1,2,3,4,5,6,7,8,9])) + '\n';
}

function shuffleFisherYates(array) {
  let i = array.length;
  while (i--) {
    const ri = Math.floor(Math.random() * i);
    [array[i], array[ri]] = [array[ri], array[i]];
  }
  return array;
}
&lt;pre&gt;&lt;/pre&gt;

这可能会被压缩为一个衬里(注意:这个衬里不会在 Google Closure Compiler 高级级别中编译):

const shuffle = array => 
  [...Array(array.length)]
    .map((el, i) => Math.floor(Math.random() * i))
    .reduce( (a, rv, i) => ([a[i], a[rv]] = [a[rv], a[i]]) && a, array);
const result = document.querySelector("pre");
for (let i=0; i<100; i+=1)
  result.textContent +=
   JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9])) + '\n';
&lt;pre&gt;&lt;/pre&gt;

【讨论】:

【解决方案2】:

这里还有一个基于 lodash _.shuffle 的示例。

const array = [
    { some: 1 },
    { some: 2 },
    { some: 3 },
    { some: 4 },
    { some: 5 },
    { some: 6 },
    { some: 7 },
  ];
console.log(_.shuffle(array));
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"&gt;&lt;/script&gt;

【讨论】:

    【解决方案3】:

    如果需要打乱元素节点集合(在 DOM 中),请先将其转换为数组:

    var wrapper = document.getElementById('someid');
    var array = Array.prototype.slice.call(wrapper.children);
    

    即使您可以使用 for 循环迭代集合,直接打乱 HTMLCollection 对象(由 children 返回)也不起作用。这让我困惑了一段时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      相关资源
      最近更新 更多