Search code examples
javascriptlodash

Shuffle some elements of an array with a specific step


I need to shuffle some elements of an array with a specific step.

I have this array of object :

[
  {
    "_id": "aze54aze",
    "boosted": false
  },
  {
    "_id": "94v2d9e3",
    "boosted": false
  },
  {
    "_id": "999f5a8az4",
    "boosted": false
  },
  {
    "_id": "e9d29a9g",
    "boosted": true
  },
  {
    "_id": "f8f2a9f6a",
    "boosted": false
  },
  {
    "_id": "pe55z8a",
    "boosted": false
  },
  {
    "_id": "pvazpd97",
    "boosted": false
  },
  {
    "_id": "ft8azefze",
    "boosted": true
  },
]

I want the boosted objects to be shuffled within the array with a step of two objects between them. In order to not put them all at the beginning of the array, I need them to be "hidden" in the array.

That means that the first boosted object will go at the first position, then two normal objects, then the second boosted object, then the other normal objects.

Can I achieve this with Lodash built-in functions ?


Solution

  • You can do this by using native ES6 javascript features like filter, reduce methods and spread syntax

    First of all, you should separate the boosted and normal array items. Then create a new array where first boosted object will go at the first position, then two normal objects, then second boosted object and so on...

    I used splice method in order to remove items from normal or boosted array after I added them to my result array. Why this ? Because at the end I need to concat the remaining elements to my result.

    var arr = [ { "_id": "aze54aze", "boosted": false }, { "_id": "94v2d9e3", "boosted": false }, { "_id": "999f5a8az4", "boosted": false }, { "_id": "e9d29a9g", "boosted": true }, { "_id": "f8f2a9f6a", "boosted": false }, { "_id": "pe55z8a", "boosted": false }, { "_id": "pvazpd97", "boosted": false }, { "_id": "ft8azefze", "boosted": true }, ] 
    
    var boosted = arr.filter(item => item.boosted);
    var boosted_copy = boosted.slice();
    var normal = arr.filter(item => !item.boosted);
    var result = boosted.reduce((res, item, i) => {
       res.push(boosted_copy.splice(0, 1)[0], ...normal.splice(0, i * 2 + 2));
       return res;
    }, []).concat(boosted_copy, normal);
    console.log(result);