Diego de Oliveira
Diego de Oliveira

Reputation: 681

Javascript - How to mix two arrays of objects with specific sorting order?

I have two array of objects. Something like this:

var arrayA = [
    {
        type: 'card',
        id: 1
    },
    {
        type: 'card',
        id: 2
    },
    {
        type: 'card',
        id: 3
    },
    {
        type: 'card',
        id: 4
    },
    {
        type: 'card',
        id: 5
    },
];

var arrayB = [
    {
        type: 'pro-tip',
        id: 10
    },
    {
        type: 'pro-tip',
        id: 11
    },
];

I want to merge these two arrays of objects, but on a specific order. Basically, what I want is that, after each N number of elements from arrayA, I want to add one element from arrayB. If N == 2 The final array would look like this:

var finalArray = [
    {
        type: 'card',
        id: 1
    },
    {
        type: 'card',
        id: 2
    },
    {
        type: 'pro-tip',
        id: 10
    },
    {
        type: 'card',
        id: 3
    },
    {
        type: 'card',
        id: 4
    },
    {
        type: 'pro-tip',
        id: 11
    },
    {
        type: 'card',
        id: 5
    },
];

Probably it is not difficult to do something like this, but I'm looking for the most elegant way to build a helper function to do that.


Edit:

Here's the function I created. It seems like it works, but there might be a simpler way to do it:

function mergeWithSteps( arrayA, arrayB, nSteps, nElementsToAdd ) {
    var finalArray = [],
        stepsCount = 0,
        elementsToAddCount = 0,
        arrayBNumberOfElements = arrayB.length;

    arrayA.forEach( function( obj ) {
        finalArray.push( obj );
        stepsCount++;

        if( stepsCount == nSteps && elementsToAddCount < arrayBNumberOfElements ) {
            finalArray.push( arrayB[ elementsToAddCount ] );
            elementsToAddCount++;
            stepsCount = 0;
        }
    } );

        return finalArray;
}

Upvotes: 0

Views: 73

Answers (3)

Hikmat G.
Hikmat G.

Reputation: 2621

You can use reduce if the initial array is not to modify.

const arrayA = [
  {
    type: 'card',
    id: 1
  },
  {
    type: 'card',
    id: 2
  },
  {
    type: 'card',
    id: 3
  },
  {
    type: 'card',
    id: 4
  },
  {
    type: 'card',
    id: 5
  },
];

const arrayB = [
  {
    type: 'pro-tip',
    id: 10
  },
  {
    type: 'pro-tip',
    id: 11
  },
];

const res = arrayA.reduce((acc, a, i) => {
  const b = arrayB[(i + 1) / 2 - 1];
  return [...acc, a, ...(b ? [b] : [])];
}, []);

console.log(res);

Upvotes: 0

Seva Kalashnikov
Seva Kalashnikov

Reputation: 4392

Here's my iterative solution using for

countA = arrayA.length;
countB = arrayB.length;
merged = [];

for (var i = 0, j = 0, m = 0; i < countA; i ++, m ++) {
    if (i > 0 && i%2 == 0 && typeof arrayB[j] !== 'undefined') {
        merged[m] = arrayB[j];
        j ++;
        m ++;
    }
    merged[m] = arrayA[i];
}
// if you'd like to place all remaining arrayB elements after arrayA is exhausted
if (countB > j) {
    for (i = j; i < countB; i++, m ++) {
        merged[m] = arrayB[i];
    }
}

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386654

You could use Array#slice for inserting the wanted item and iterate arrayB from the end, because every splicing changes the indices after the insertation index.

var arrayA = [{ type: 'card', id: 1 }, { type: 'card', id: 2 }, { type: 'card', id: 3 }, { type: 'card', id: 4 }, { type: 'card', id: 5 }],
    arrayB = [{ type: 'pro-tip', id: 10 }, { type: 'pro-tip', id: 11 }],
    place = 2,
    i = arrayB.length;

while (i) {
    arrayA.splice(i * place, 0, arrayB[--i]);
}

console.log(arrayA);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 3

Related Questions