1

I am trying to create a simngle array of multiple values obtained from an input array of objects. Ideally I'd like to use "ES5" features to do this.

I need to transform an object such as this:

{
  image: "bat",
  count: 5
}

into this array [bat, bat, bat, bat, bat]

I think the code is the fastest way to explain:

//game object state
var gameObj = {
objects: [
  {
    image: "bat",
    count: 5
  },
  {
    image: "spider",
    count: 4
  },
  {
    image: "frankie",
    count: 3
  }
],
imagesArr: [],
}

function gameObjectArrayBuilder(obj) {
  var resultArr = [];
  resultArr = obj.map(buildArr);

  function buildArr(prop) {
    var image = prop.image;
    var count = prop.count;
    while (prop.count > 0) {
      prop.count--
      return prop.image
    }
  }
  return resultArr;

}

gameObj.imagesArr = gameObjectArrayBuilder(gameObj.objects);

//View result
var html = document.querySelector("#content");
html.innerHTML = gameObj.imagesArr;
console.log(gameObj.imagesArr)

//Result should be
//[bat, bat, bat, bat, bat, spider, spider, spider, spider, frankie, frankie, frankie]
<div id="content">

</div>
Dacre Denny
  • 26,362
  • 5
  • 28
  • 48
dwigt
  • 549
  • 1
  • 6
  • 15

6 Answers6

3

To obtain an array of duplicate string values (ie "bat"), where the length of the array corresponds to a supplied variable (ie "obj.count"), you could do the following:

const obj = { image: "bat", count: 5 };

const arr = Array.from({ length : obj.count }, () => (obj.image));

console.log(arr);

You could then build upon this to populate an array based on multiple input objects like this:

var gameObj = {
  objects: [{
      image: "bat",
      count: 5
    },
    {
      image: "spider",
      count: 4
    },
    {
      image: "frankie",
      count: 3
    }
  ],
  imagesArr: [],
}

// Use reduce to obtain compounded array from all input objects
gameObj.imagesArr = gameObj.objects.reduce((acc, obj) => {

  // Concat acc array with resulting array from current obj
  return acc.concat(Array.from({ length: obj.count }, () => (obj.image)))

}, []);


console.log(gameObj.imagesArr);
Dacre Denny
  • 26,362
  • 5
  • 28
  • 48
1

Solution For your example

//game object state
var gameObj = {
objects: [
  {
    image: "bat",
    count: 5
  },
  {
    image: "spider",
    count: 4
  },
  {
    image: "frankie",
    count: 3
  }
],
imagesArr: [],
}

function gameObjectArrayBuilder(obj) {
  var resultArr = [];
  obj.forEach((ele)=>{resultArr.push(...buildArr(ele))});

  function buildArr(prop) {
    var image = prop.image;
    var count = prop.count;
    var temp = []
    while (prop.count > 0) {
      prop.count--
      temp.push(prop.image)
    }
    return temp
  }
  return resultArr;

}

gameObj.imagesArr = gameObjectArrayBuilder(gameObj.objects);


//View result
var html = document.querySelector("#content");
html.innerHTML = gameObj.imagesArr;
console.log(gameObj.imagesArr)

//Result should be
//[bat, bat, bat, bat, bat, spider, spider, spider, spider, frankie, frankie, frankie]
<div id="content">

</div>
Vaibhav Singh
  • 822
  • 7
  • 20
1

You can use a combination of new Array and the reduce method for your case:

var gameObj = {
  objects: [{
      image: "bat",
      count: 5
    },
    {
      image: "spider",
      count: 4
    },
    {
      image: "frankie",
      count: 3
    }
  ],
  imagesArr: [],
};

function repeatImages(acc, item, idx) {

  if (!(acc instanceof Array)) {
    acc = [];
  }

  return acc.concat(new Array(item.count).fill(item.image));

}

gameObj.imagesArr = gameObj.objects.reduce(repeatImages, []);

console.log(gameObj.imagesArr);
darklightcode
  • 2,317
  • 1
  • 12
  • 14
1

You could take the count and loop this count as long as it has a truthy value.

Instead of mapping (Array#map), I would reduce (Array#reduce) the array, because the result set is an array with a count of items. In new user agents, Array#flatMap would work, but here an accumulator is necessary for getting all same items.

function gameObjectArrayBuilder(array) {
    function buildArr(accumulator, object) {
        var count = object.count;
        while (count--) accumulator.push(object.image);
        return accumulator;
    }
  
    return array.reduce(buildArr, []);
}

var gameObj = { objects: [{ image: "bat", count: 5 }, { image: "spider", count: 4 }, { image: "frankie", count: 3 }], imagesArr: [] };

gameObj.imagesArr = gameObjectArrayBuilder(gameObj.objects);

var html = document.querySelector("#content");
html.innerHTML = gameObj.imagesArr;
console.log(gameObj.imagesArr)
<div id="content"></div>
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
  • Thank you everyone! I got it working with your solutions. Will come back to this thread to understand map, reduce, filter and while loops better. – dwigt Oct 04 '19 at 11:03
1

You can use flatMap to produce the same result with less number of codes.

//game object state
var gameObj = {
objects: [
  {
    image: "bat",
    count: 5
  },
  {
    image: "spider",
    count: 4
  },
  {
    image: "frankie",
    count: 3
  }
],
imagesArr: [],
}

function gameObjectArrayBuilder(obj) {
  var resultArr = obj.flatMap( f=> {
 return [...Array(f.count).fill(f.image)]
});
  
  return resultArr;

}

gameObj.imagesArr = gameObjectArrayBuilder(gameObj.objects);


//View result
var html = document.querySelector("#content");
html.innerHTML = gameObj.imagesArr;
console.log(gameObj.imagesArr)

//Result should be
//[bat, bat, bat, bat, bat, spider, spider, spider, spider, frankie, frankie, frankie]
<div id="content">

</div>
thuva4
  • 1,007
  • 7
  • 11
1

You can just use a for cycle to add items to a tmp array, then return it:

//game object state
var gameObj = {
objects: [
  {
    image: "bat",
    count: 5
  },
  {
    image: "spider",
    count: 4
  },
  {
    image: "frankie",
    count: 3
  }
],
imagesArr: [],
}

function gameObjectArrayBuilder(obj)
{
  var resultArr = [];
  resultArr = obj.map(buildArr);

  function buildArr(prop)
  {
    var image = prop.image;
    var count = prop.count;
    
    // USE A TMP ARRAY
    let tmpArr = []
    for (let j=0; j<count; j++) {
      tmpArr.push(prop.image);
    }
    
    return tmpArr
  }
  
  return resultArr;
}

gameObj.imagesArr = gameObjectArrayBuilder(gameObj.objects);


//View result
var html = document.querySelector("#content");
html.innerHTML = gameObj.imagesArr;
<div id="content">

</div>
GrafiCode
  • 1,698
  • 2
  • 22
  • 21