根据频率对对象数组进行排序,但保留重复的元素

Sort an array of objects based on frequency but keep repeated elements

我有一个对象数组,

 const myArray = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];
    
myArray.sort((a, b) => a.k_id - b.k_id);

console.log(myArray);

我希望根据 k_id 及其出现次数(降序)对其进行排序。但是,必须保留所有元素,因为我在对象中有其他值。其他键值对可以是任意顺序。 (我在这里只用两个键值对简化了我的问题,但实际数组有超过 15 个键值对)

产生的输出:

(8) [{id:1,k_id:1},{id:3,k_id:1},{id:2,k_id:2},{id:6,k_id:2},{id:7,k_id:2},{id:4,k_id:3},{id:5,k_id:3},{id:8,k_id:4}]

预期输出,因为我需要将它们按如下方式排序,因为 k_id:2 发生的次数多于 k_id:1:

myArray = [{id:6, k_id:2},{id:7, k_id:2},{id:2, k_id:2},{id:3, k_id:1},{id:1, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:8, k_id:4}];

正在寻找这样的东西?

inp.sort((a, b) => 
    inp.filter(c => c.k_id === b.k_id).length -
    inp.filter(c => c.k_id === a.k_id).length
);
// sorting a vs b by counting the occurency of each k_id property value
// using filter

const inp = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];


console.log(
  inp.sort((a, b) => inp.filter(c => c.k_id === b.k_id).length - inp.filter(c => c.k_id === a.k_id).length)
)

我建议首先创建频率查找。下面我使用了 reduce with a Map, but you can use a regular object and a for loop to build the same look up. The Map has keys which are the k_id, and the value of each k_id is the number of times k_id occurs. Creating the lookup means you don't need to loop through your array each iteration of your sort. You can then use .sort() and sort by the occurrences for each key_id stored within the frequency map. As this uses .sort(), the sort is stable,因此具有相同 k_id 的项目将保持它们与原始数组的相对顺序:

const myArray = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];

const freq = myArray.reduce((acc, {k_id}) => acc.set(k_id, (acc.get(k_id) || 0) + 1), new Map);
myArray.sort((a, b) => freq.get(b.k_id) - freq.get(a.k_id));

console.log(myArray);

试试这个,我不确定它是否可以扩展,但它工作正常。

const myArray = [{id:1, k_id:1},{id:2, k_id:2},{id:3, k_id:1},{id:4, k_id:3},{id:5, k_id:3},{id:6, k_id:2},{id:7, k_id:2},{id:8, k_id:4}];

(()=>{
    const keys = {}
    const newArray = [];
    /**
     * Determenin every keys count
     */
    for(const one of myArray){
        // if the key is not yet registered in keys
        // initialize 0 and add one either way
        // on the key count
        keys[one.k_id] = (keys[one.k_id] || 0) + 1;
    }
    console.log(keys)
    //
    function GetTheHighestFrequency () {
        /**
         * @return {object} highest
         * 
         * containing a key or K_id
         * and its frequency count 
         */
        let highest = { key:0,frequency:0 }; 
        for(const [key,value] of Object.entries(keys)){
            if(value > highest.frequency)
            highest = { key,frequency:value };
        }   
        return highest
    }
    //
    // return new array
    for(const each of Object.keys(keys)){
        // request the highest frequency key K_id
        const highest = GetTheHighestFrequency();
        //
        // Add (Push) objects in the newArray 
        //
        for(const one of myArray){
            // add an object if
            // if  the K_id matches the current 
            // highest key value
            if(String(one.k_id) === highest.key)
            newArray.push(one)
        }
        delete keys[highest.key]
    }
    console.log("the result is = ",newArray)
})()