Javascript js洗牌对象数组,同时保留一些顺序

Javascript js洗牌对象数组,同时保留一些顺序,javascript,random,shuffle,Javascript,Random,Shuffle,如何高效地洗牌如下所示的对象数组: array = [ {from: "john", requestNum: 1}, {from: "jack", requestNum: 1}, {from: "jill", requestNum: 1}, {from: "john", requestNum: 2}, {from: "jane", requestNum: 1}] 我想随机地洗牌这些对象,但是来自

如何高效地洗牌如下所示的对象数组:

array = [
{from: "john", requestNum: 1},
{from: "jack", requestNum: 1},
{from: "jill", requestNum: 1},
{from: "john", requestNum: 2},
{from: "jane", requestNum: 1}]
我想随机地洗牌这些对象,但是来自相同名称的请求必须保持它们的相对顺序。所以,无论约翰的第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);
for(设i=array.length-1;i>0;i--){
常数j=数学楼层(数学随机()*(i+1));
[array[i],array[j]=[array[j],array[i]];
}
控制台日志(“洗牌”);
console.log(数组);
常量索引={};
for(设i=0;ib.requestNum){
返回1;
}
返回0;
}
for(var输入请求){
//日志(请求[key]);
如果(请求[键]。长度>0){
const sorted=请求[key]。排序(比较);
//控制台日志(已排序);
请求[键]=已排序;
}
}
常量数组=[];
for(var键入索引){
for(设i=0;i<索引[key]。长度;i++){
SorterDarray[index[key][i]=请求[key][i];
}
}
控制台日志(“已排序”);
控制台日志(Darray);

有没有办法提高它的效率?

我攻击它的方法是将所有对象映射到一个用户。使用所有姓名的列表,将其洗牌。然后从名单上跳出来

//Fisher-Yates Shuffle
函数洗牌(数组){
var currentIndex=array.length,
时间值,随机指数;
而(0!==currentIndex){
randomIndex=Math.floor(Math.random()*currentIndex);
currentIndex-=1;
临时值=数组[currentIndex];
数组[currentIndex]=数组[randomIndex];
数组[randomIndex]=临时值;
}
返回数组;
}
常量数组=[
{from'john',requestNum:1},
{from:'jack',requestNum:1},
{发件人:'jill',requestNum:1},
{from'john',requestNum:2},
{from:'jane',requestNum:1},
];
const users=array.reduce((acc,obj)=>{
//存储对名称的引用
附件名称推送(obj.from);
//将对对象的引用存储在数组中
acc.data[obj.from]=acc.data[obj.from]| |[];
acc.data[obj.from].push(obj);
返回acc;
}, {
姓名:[],
数据:{}
});
//洗牌名称数组
const shuffledNames=shuffle(users.names);
//循环遍历已洗牌的名称,并从该用户的数组中移除项
const shuffledObjs=shuffledNames.map(name=>users.data[name].shift());

console.log(shuffledObjs)这样做将非常复杂。将其拆分为一个数组,其中内部数组是来自同一个人的请求,怎么样?然后使用答案洗牌外部数组。(我想你可以
.flat
然后再回到一维。)太棒了!到目前为止,您尝试了什么/您编写了什么代码试图解决这个问题?你被卡在哪了?请将这些问题的答案编辑到问题正文中,因为堆栈溢出不会为您编写代码。另请参见:您尚未定义什么是对象john、jack。。。元素