Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Improve Array transformation in Javascript

Suppose I have a input array like the following

var inputArray = [
    {a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1},
    {a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2},
    {a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3},
    {a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4},
    {a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5},
    {a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1},
    {a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2},
    {a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3},
    {a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4},
    {a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5}
]

I want to transform my inputArray to the following outputArray

var outputArray = [
    {
        a: 1,
        b: 1,
        c: 1,
        d: 1,
        values:{
            "1":{value: 1},
            "2":{value: 2},
            "3":{value: 3},
            "4":{value: 4},
            "5":{value: 5}
        }
    },
    {
        a: 1,
        b: 2,
        c: 1,
        d: 1,
        values:{
            "1":{value: 1},
            "2":{value: 2},
            "3":{value: 3},
            "4":{value: 4},
            "5":{value: 5}
        }
    }
]

That means, I need create a dictionary for same property of a, b, c and d where the value of property rank is the key of the dictionary and the value of the dictionary is an object where the only property is value.

We assume that the inputArray will not be sorted with respect to the combination of a, b, c and d. So, my approach is like this,

(function(){
    var inputArray = [
        {a: 1, b: 1, c: 1, d: 1, value: 1, rank: 1},
        {a: 1, b: 1, c: 1, d: 1, value: 2, rank: 2},
        {a: 1, b: 1, c: 1, d: 1, value: 3, rank: 3},
        {a: 1, b: 1, c: 1, d: 1, value: 4, rank: 4},
        {a: 1, b: 1, c: 1, d: 1, value: 5, rank: 5},
        {a: 1, b: 2, c: 1, d: 1, value: 1, rank: 1},
        {a: 1, b: 2, c: 1, d: 1, value: 2, rank: 2},
        {a: 1, b: 2, c: 1, d: 1, value: 3, rank: 3},
        {a: 1, b: 2, c: 1, d: 1, value: 4, rank: 4},
        {a: 1, b: 2, c: 1, d: 1, value: 5, rank: 5}
    ]

    var temp = inputArray.sort(function(valA, valB){
        if(valA.a === valB.a){
            if(valA.b === valB.b){
                if(valA.c === valB.c){
                    return valA.d < valB.d;
                }
                return valA.c < valB.c;
            }
            return valA.b < valB.b;
        }
        return valA.a < valB.a;
    });

    var outputArray = [],
    currentIndex = 0;
    for(var i = 0; i < inputArray.length; i++){
        if(i > 0 && isConfigurationSame(inputArray[i], inputArray[i-1])){
            outputArray[currentIndex-1].values[inputArray[i].rank] = {
                value: inputArray[i].value
            }
        }
        else{
            outputArray.push(mapToOutputArrayObject(inputArray[i]));
            currentIndex++;
        }
    }
    console.log(outputArray);

    function isConfigurationSame(A, B) {
        return A.a === B.a
            && A.b === B.b
            && A.c === B.c
            && A.d === B.d;
    }

    function mapToOutputArrayObject(val){
        var row = {};
        row['a'] = val.a;
        row['b'] = val.b;
        row['c'] = val.c;
        row['d'] = val.d;
        row['values'] = {};
        row.values[val.rank] = {
            value: val.value
        }
        return row;
    }
}());

But the problem is, this thing is really getting more time if the length of input array is huge. This multi-criteria sorting also taking much time.

Is there any better approach to accomplish the result more efficiently with less time?

Thanks for your time and patience.

UPDATE: The values of a, b, c and d can be integer or null.

like image 220
Adnan Sharif Avatar asked Jul 06 '26 21:07

Adnan Sharif


1 Answers

You could create a hashtable and generate a unique key based on a, b, c and d:

const hash = {};

for(const { a, b, c, d, value, rank } of array) {
  const key = JSON.stringify([a, b, c, d]); // generate a unique, but not random key
  if(hash[key]) { // check if it already exists,
   hash[key].values[rank] = value; // merge
  } else {
   hash[key] = { // create a new entry
     a, b, c, d,
     values: { [rank]: value },
   };
  }
}

const result = Object.values(hash); // turn the object into an array

That is O(n), which is better as the time complexity of any .sort implementation (but it only works if a, b, c and d are serializable (like in this case)).

like image 80
Jonas Wilms Avatar answered Jul 09 '26 10:07

Jonas Wilms



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!