0

I have an array of objects,

 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);

I want it to be sorted based on the k_id and it occurrences(descending frequency). But, have to keep all the elements as I have other values in the objects. Other key, value pairs can be in any order. (I have simplified my issue here with only two key, value pairs but the actual array have more than 15 key, value pairs)

Output Produced:

(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}]

Expected output, because I need them to be sorted like below as k_id:2 occured more than 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}];
5
  • 1
    Please read How to Ask and minimal reproducible example before posting a question. Commented Feb 2, 2022 at 12:38
  • The example of the output doesn't make sense. The k_id values are in this order: 2,...2,..1,...1,...3,...3,...4 ? Commented Feb 2, 2022 at 12:49
  • Why is it {id:6, k_id:2},{id:7, k_id:2},{id:2, k_id:2} and not {id:2, k_id:2}, {id:6, k_id:2},{id:7, k_id:2}, as items here will keep their relative orderings, or does it not matter? Commented Feb 2, 2022 at 12:52
  • @NickParsons it doesn't matter. just the k_id shoud be ordered in the count of it's occurences. id and other key-value pairs can be in any order Commented Feb 2, 2022 at 12:54
  • @zer00ne It's 2,...2,...2,..1,...1,...3,...3,...4 Commented Feb 2, 2022 at 12:54

3 Answers 3

1

Looking for something like this?

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)
)

Sign up to request clarification or add additional context in comments.

Comments

1

try this out, I'm not sure if it would scale but, it works fine.

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)
})()

Comments

0

I would suggest first creating a frequency lookup. Below I've used 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, so items with the same k_id will keep their relative ordering from the original array:

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);

1 Comment

Why the dv? If something is wrong with my answer or if I've misunderstood the question please point it out and I will try and fix it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.