微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对象的javascript数组添加排名但不更改主数组的顺序

如何解决对象的javascript数组添加排名但不更改主数组的顺序

我想根据 rank 值在每个元素上添加一个 totalpremium 键(但我不想更改数组内对象的顺序),我的当前代码工作正常,但它改变了我不想做的主对象数组的顺序。

对象数组:

 [
  {
    totalcount: 2834682,totalpremium: 652553820
  },{
    totalcount: 1380674,totalpremium: 430713235
  },{
    totalcount: 862119,totalpremium: 165983898
  }
]

工作职能

// add rank to each object
function rank_by_key(array,key_name) {

    if (key_name) {

        array.sort(function (a,b) {
            return b[key_name] - a[key_name];
        });

        var rank = 1;
        for (var i = 0; i < array.length; i++) {
            if (i > 0 && array[i][key_name] < array[i - 1][key_name]) {
                rank++;
            }
            array[i].rank = rank;
        }
    }
    return array;
}


ranked_result = rank_by_key(array,'totalpremium');

预期输出

      [
        {
          "totalcount": 2834682,"totalpremium": 110,"rank": 2
        },{
          "totalcount": 1380674,"totalpremium": 121,"rank":1
        },{
          "totalcount": 862119,"totalpremium": 100,"rank": 3
        }
      ]
    

电流输出

      [
        {
          "totalcount": 1380674,{
          "totalcount": 2834682,"rank": 3
        }
      ]
    

解决方法

这会创建一个 ranks 数组,然后我们可以在创建新属性时引用它

let data = [
  {
    totalcount: 2834682,totalpremium: 652553820
  },{
    totalcount: 1380674,totalpremium: 43071324534435
  },{
    totalcount: 862119,totalpremium: 165983898
  }
]

let ranks = data.map(e => e.totalpremium).sort((a,b) => b-a)
let ranked = data.map( e=> ({...e,rank: (ranks.indexOf(e.totalpremium)+1)}));

console.log(ranked)

,

您只需要一个 sort 字段,别无他物。以下数组索引是您的预期等级。 您可以按如下方式进行操作(如果您需要在元素中显式包含 rank):

  • sort 您的数组副本(sort 确实会改变原始数组,这就是您需要创建副本的原因),
  • 然后使用 mapmap 也不会改变原始数组)。

代码示例:

const data = [{totalcount:2834682,totalpremium:652553820},{totalcount:862119,totalpremium:165983898},{totalcount:1380674,totalpremium:430713235}];

const res = [...data].sort((a,b) => b.totalpremium - a.totalpremium)
                     .map((e,i) => ({rank: i + 1,...e}))
                   
                
console.log("Result: ",res)
console.log("Original data: ",data)
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore this */

,

可以先对对象进行排序,循环遍历结果,得到对应的对象,并将索引赋值给rank属性:

Object.entries(arr[0]).sort(([,a],[,b]) => {
  return b.totalpremium - a.totalpremium
}).forEach((e,i) => arr[0][(e[0])].rank = i + 1);

结果:

const arr = [{
  "A": {
    "totalcount": 2834682,"totalpremium": 110
  },"B": {
    "totalcount": 1380674,"totalpremium": 121
  },"C": {
    "totalcount": 862119,"totalpremium": 100
  }
}]
Object.entries(arr[0]).sort(([,b])=>{return b.totalpremium-a.totalpremium}).forEach((e,i) => arr[0][(e[0])].rank = i+1);
console.log(arr);

,

从您提供的代码来看,您似乎希望排名考虑平等,例如[10,20,30,20] 将排在 [3,2,1,2] 而不是 [4,3]

性能瓶颈将是键的排序,但我们对此无能为力。

这是我得到的,使用了很好的旧函数和中间变量。 一些 ES6 语法糖是有代价的,而集合似乎很有魅力。当老式方法似乎提供了良好的可读性/性能权衡时,我又回到了老式方法,但这当然是很有争议的。

function rank_according_to (data,key_name)
{
    // collect unique key values
    let unique_keys = new Set();
    for (let i = 0 ; i != data.length ; i++) unique_keys.add(data[i][key_name]);
    
    // sort unique key values
    let sorted_keys = [...unique_keys].sort( (a,b) => b-a );
    
    // associate a rank to each value
    let rank_of_key = [];
    for (let i = 0 ; i != sorted_keys.length ; i++) rank_of_key[sorted_keys[i]] = i+1;
    
    // Option 1: Put the ranks into the original array
    //for (let i = 0 ; i != data.length ; i++) data[i].rank = rank_of_key[data[i][key_name]];

    // Option 2: put the ranks into a deep copy
    return data.map (record => ({ ...record,rank: (rank_of_key[record[key_name]]) }) );
}

我更改了您的数据集,使其具有更易读的数字和具有相同键值的情况:

console.log (sample)

Array(4) [ {…},{…},{…} ]
​0: Object { key_one: 123,key_two: 121 }
​1: Object { key_one: 135,key_two: 110 }
​2: Object { key_one: 123,key_two: 151 }
​3: Object { key_one: 100,key_two: 100 }

console.log (rank_according_to (sample,"key_one"));

0: Object { key_one: 123,key_two: 121,rank: 2 }
1: Object { key_one: 135,key_two: 110,rank: 1 }
2: Object { key_one: 123,key_two: 151,rank: 2 }
3: Object { key_one: 100,key_two: 100,rank: 3 }

console.log (rank_according_to (sample,"key_two"));

​0: Object { key_one: 123,rank: 2 }
​1: Object { key_one: 135,rank: 3 }
​2: Object { key_one: 123,rank: 1 }
​3: Object { key_one: 100,rank: 4 }

现在如果你问我,假设效率不是问题,你可以通过将原始索引保存在“original_order”属性中来省去一些麻烦,这样你就可以在你完成后将数组排序回原位完成生成排名。

无论如何,我对依赖浅拷贝副作用的设计不太满意。它令人困惑,更难维护,并不比许多其他可能的解决方案更有效,而且可能比从一开始就设计更坚固的解决方案的额外成本浪费更多的调试时间。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。