【问题标题】:Mapping a compounded array from objects with JavaScript [duplicate]使用 JavaScript 从对象映射复合数组 [重复]
【发布时间】:2019-10-04 08:26:56
【问题描述】:

我正在尝试创建一个从输入对象数组获得的多个值的单一数组。理想情况下,我想使用“ES5”功能来做到这一点。

我需要像这样转换一个对象:

{
  image: "bat",
  count: 5
}

进入这个数组[bat, bat, bat, bat, bat]

我认为代码是最快的解释方式:

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

【问题讨论】:

  • 你总是在while的第一次迭代中返回
  • 更好的答案:const arr = gameObj.objects.flatMap(e =&gt; Array(e.count).fill(e.image));

标签: javascript


【解决方案1】:

要获得一个重复字符串值的数组(即“bat”),其中数组的长度对应于提供的变量(即“obj.count”),您可以执行以下操作:

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

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

console.log(arr);

然后您可以在此基础上构建一个基于多个输入对象的数组,如下所示:

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

【讨论】:

    【解决方案2】:

    您可以针对您的案例使用new Arrayreduce 方法的组合:

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

    【讨论】:

    • 你还必须为 fill 提供一个 polyfill,因为 OP 使用的是 ES5。
    • 你为什么在reduce迭代中检查acc instanceof Array(并设置为一个空数组)?
    【解决方案3】:

    您的示例的解决方案

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

    【讨论】:

      【解决方案4】:

      只要它具有真实值,您就可以获取计数并循环该计数。

      我将减少 (Array#reduce) 数组,而不是映射 (Array#map),因为结果集是一个包含项目计数的数组。在新的用户代理中,Array#flatMap 可以工作,但这里需要一个累加器来获取所有相同的项目。

      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)
      &lt;div id="content"&gt;&lt;/div&gt;

      【讨论】:

      • 谢谢大家!我让它与您的解决方案一起使用。将回到这个线程以更好地理解 map、reduce、filter 和 while 循环。
      【解决方案5】:

      您可以使用for 循环将项目添加到 tmp 数组,然后将其返回:

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

      【讨论】:

        【解决方案6】:

        您可以使用flatMap 以更少的代码产生相同的结果。

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

        【讨论】:

        • 你不需要.map(...).flatMap,只需要.flatMap(...)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-12-04
        • 2020-12-26
        • 1970-01-01
        • 2020-03-21
        • 1970-01-01
        • 2016-02-28
        • 1970-01-01
        相关资源
        最近更新 更多