【问题标题】:js shuffle array of objects while retaining some orderjs 随机播放对象数组,同时保留一些顺序
【发布时间】:2021-03-03 16:45:25
【问题描述】:

如何有效地洗牌看起来像这样的对象数组:

array = [
{from: "john", requestNum: 1},
{from: "jack", requestNum: 1},
{from: "jill", requestNum: 1},
{from: "john", requestNum: 2},
{from: "jane", requestNum: 1}]

我想随机打乱这些对象,但是来自同名的请求必须保留它们的相对顺序。因此,无论 Johns 请求编号 2 最终以随机排列的数组形式出现,它都必须在其请求 n1 之后。

我想出的并且是功能性的,但可能真的很笨拙的是:

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

console.log("SHUFFLED");
console.log(array);

const indexes = {};
for (let i = 0; i < array.length; i++) {
  if (indexes[array[i].from]) {
    indexes[array[i].from].push(i);
  } else {
    indexes[array[i].from] = [i];
  }
}

const requests = {};
for (let i = 0; i < array.length; i++) {
  if (requests[array[i].from]) {
    requests[array[i].from].push(array[i]);
  } else {
    requests[array[i].from] = [array[i]];
  }
}

function compare(a, b) {
  if (a.requestNum < b.requestNum) {
    return -1;
  }
  if (a.requestNum > b.requestNum) {
    return 1;
  }
  return 0;
}

for (var key in requests) {
  //console.log(requests[key]);
  if (requests[key].length > 0) {
    const sorted = requests[key].sort(compare);
    // console.log(sorted);
    requests[key] = sorted;
  }
}

const sortedArray = [];
for (var key in indexes) {
  for (let i = 0; i < indexes[key].length; i++) {
    sortedArray[indexes[key][i]] = requests[key][i];
  }
}
console.log("SORTED");
console.log(sortedArray);

有什么方法可以提高效率吗?

【问题讨论】:

  • 这样做会非常复杂。将其拆分为数组数组如何,其中内部数组是来自同一个人的请求?然后你使用this question 的答案来洗牌外部数组。 (我想你可以在之后 .flat 它回到一维。)
  • 太棒了!到目前为止,您尝试了什么/您编写了哪些代码来尝试解决此问题?你在哪里特别卡住了?请将这些问题的答案编辑到您的问题正文中,因为 Stack Overflow 不会为您编写代码。另见:How to Ask
  • 你还没有定义什么对象是 john, jack... 元素

标签: javascript random shuffle


【解决方案1】:

我攻击它的方法是将所有对象映射到用户。使用所有名称的列表,将它们随机排列。而不是从列表中弹出。

// Fisher-Yates Shuffle
function shuffle(array) {
  var currentIndex = array.length,
    temporaryValue, randomIndex;
  while (0 !== currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }
  return array;
}

const array = [
  {from: 'john', requestNum: 1},
  {from: 'jack', requestNum: 1},
  {from: 'jill', requestNum: 1},
  {from: 'john', requestNum: 2},
  {from: 'jane', requestNum: 1},
];

const users = array.reduce((acc, obj) => {
  // store a reference to the name
  acc.names.push(obj.from);
  // store the reference to the object in an array
  acc.data[obj.from] = acc.data[obj.from] || [];
  acc.data[obj.from].push(obj);
  return acc;
}, {
  names: [],
  data: {}
});

// Shuffle the array of names
const shuffledNames = shuffle(users.names);

// Loop over the shuffled names and remove the items from the array for that user
const shuffledObjs = shuffledNames.map(name => users.data[name].shift());

console.log(shuffledObjs);

此代码假设数组按 requestNum 顺序排列。如果从一开始就不是这种情况,则需要在开始时进行排序。

【讨论】:

    猜你喜欢
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多