【问题标题】:Javascript for loop return results to nested arrayJavascript for循环将结果返回到嵌套数组
【发布时间】:2020-08-08 13:41:10
【问题描述】:

我正在尝试将嵌套数组中的数据选择返回到新的嵌套数组,但数据只是被推入数组。

var selection = [0,1,3,4];
var allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']]
var selectedProductData = []

for(var apd=0; apd<allProductData.length; apd++) {
  for(var spd=0; spd<allProductData[apd].length; spd++) {
    for(var s=0; s<selection.length; s++) {
      if(allProductData[apd].indexOf(allProductData[apd][spd]) === selection[s]) {
        selectedProductData.push(allProductData[apd][spd])
      }
    }
  }
}
console.log(selectedProductData)

这将返回以下内容

[
  "Item1Sku","Item1Name","Item1Price","Item1Available",
  "Item2Sku","Item2Name","Item2Price","Item2Available",
  "Item3Sku","Item3Name","Item3Price","Item3Available"
]

我想要的是

[
  ["Item1Sku","Item1Name","Item1Price","Item1Available"],
  ["Item2Sku","Item2Name","Item2Price","Item2Available"],
  ["Item3Sku","Item3Name","Item3Price","Item3Available"]
]

这方面的任何帮助都会很棒。

【问题讨论】:

  • ... 寻找一种方法,对于给定的数组,遇到 2 次 1:1 关系,因此,在我看来,最优雅/可读的解决方案将是完全基于 @ 987654321@.
  • @PeterSeliger,复杂更好......作为公认的答案。叹息。
  • @NinaScholz ... 同意,但接受 A 的优点是,OP 显然可以回溯/重现/理解代码中概念性思考不够仔细的点。额外的答案给了 OP 一些思考和学习/成长的东西。

标签: javascript arrays loops for-loop


【解决方案1】:

您可以在所需索引处映射数据和值。

const
    selection = [0, 1, 3, 4],
    allProductData = [['Item1Sku', 'Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku', 'Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku', 'Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']],
    selectedProductData = allProductData.map(values => selection.map(i => values[i]));

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

【讨论】:

    【解决方案2】:

    使用Array.prototype.reduce 减少数组并检查每个当前元素的索引是否在选择数组内,如果是则推送它。

    const selection = [0, 1, 3, 4];
    const allProductData = [
      ['Item1Sku', 'Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'],
      ['Item2Sku', 'Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'],
      ['Item3Sku', 'Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']
    ];
    
    const selectedProductData = allProductData.reduce((acc, curr) => {
      const filtered = curr.filter((product, idx) => selection.includes(idx));
    
      if (filtered.length) {
        acc.push(filtered);
      }
      return acc;
    }, []);
    
    console.log(selectedProductData);

    【讨论】:

      【解决方案3】:

      使用for...of 而不是i=0;i&lt;x;i++,它更具可读性并且可以帮助您处理流程。

      您还可以在第一个循环中访问每个元素索引,而不是设置 selection 数组。你仍然会只写一次并节省一个循环。

      var allProductData = [['Item1Sku', 'Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'],['Item2Sku', 'Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'],['Item3Sku', 'Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
      var selectedProductData = [];
      
      for (let data of allProductData) {
        selectedProductData.push([data[0], data[1], data[3], data[4]]);
      }
      
      console.log(selectedProductData)

      【讨论】:

        【解决方案4】:

        您应该在第一个 for 循环中创建另一个数组,并首先将结果推送到该数组中,然后将该数组推送到最终数组中:

        var selection = [0,1,3,4];
        var allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']]
        var selectedProductData = []
        
        for(var apd=0; apd<allProductData.length; apd++) {
          var temp = []; // declare an array here
          for(var spd=0; spd<allProductData[apd].length; spd++) {
            for(var s=0; s<selection.length; s++) {
              if(allProductData[apd].indexOf(allProductData[apd][spd]) === selection[s]) {
                temp.push(allProductData[apd][spd]); // push the result 
              }
            }
          }
          selectedProductData.push(temp); // push the array into the final array
        }
        console.log(selectedProductData)

        【讨论】:

          【解决方案5】:

          使用 array.map 和 array.filter。

          var selection = [0,1,3,4];
          var allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
          
          let result = allProductData.map(data => {
              return data.filter((el, ind) => selection.indexOf(ind)!=-1);
          })
          
          console.log(result);

          【讨论】:

            【解决方案6】:

            类似下面的 sn-p 可以完成您想要的工作。 另请参阅:

            let selection = [0,1,3,4];
            let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
            let filtered = allProductData.map(item => item.filter((val,index) => selection.includes(index)));
            console.log(filtered);

            关于这个语法(下面的sn-p)有很多噪音。在cmets 上,关于filter() 中的回调函数必须评估为true 的事实。 MDN 中的实际单词是:

            函数是一个谓词,用来测试数组的每个元素。返回 保留元素为true,否则为false

            let selection = [0,1,3,4];
            let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => {
              if(selection.includes(index)) {
                return val;
              }
              })
            );
            console.log(filtered);

            因此,这里有一些示例可以执行完全相同的操作而不会引发错误。在所有情况下,.filter() 返回的都是符合回调函数条件的逻辑真。

            let selection = [0,1,3,4];
            let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => {
                if(selection.includes(index)) {
                  return index > 3; // this will return only the itemXAvailability
                }
              })
            );
            console.log(filtered);

            上面的 sn-p 可以这样重写。

            let selection = [0,1,3,4];
            let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => selection.includes(index) && index > 3)
            );
            console.log(filtered);

            另外两个示例使用Boolean true, false 作为要测试的数组的值。

            let selection = [0,1,3,4];
            let allProductData = [[true,true, false, true, false, true], [true,true,true,true,true,true], [false,false,false,false,false,false]];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => selection.includes(index) && index > 3)
            );
            console.log(filtered);
            filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));

            注意输出的不同。

            let selection = [0,1,3,4];
            let allProductData = [[true,true, false, true, false, true], [true,true,true,true,true,true], [false,false,false,false,false,false]];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => {
                if(selection.includes(index) && index > 3) {
                  return val;
                }
                })
            );
            console.log(filtered);
            filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));

            另外两个使用数字的例子。值为0 时输出不同。

            let selection = [0,1,3,4];
            let allProductData = [[1,2,3,4,5,6], [6,5,4,3,2,1], [8,8,8,8,0,8]];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => selection.includes(index) && index > 3)
            );
            console.log(filtered);
            filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));

            let selection = [0,1,3,4];
            let allProductData = [[1,2,3,4,5,6], [6,5,4,3,2,1], [8,8,8,8,0,8]];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => {
                if(selection.includes(index) && index > 3) {
                  return val;
                }
                })
            );
            console.log(filtered);
            filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));

            使用null 作为我们的值会有什么不同。

            let selection = [0,1,3,4];
            let allProductData = [[null,null,null,null,null,null], [null,null,null,null,null,null], [null,null,null,null,null,null]];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => selection.includes(index) && index > 3)
            );
            console.log(filtered);
            filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));

            let selection = [0,1,3,4];
            let allProductData = [[null,null,null,null,null,null], [null,null,null,null,null,null], [null,null,null,null,null,null]];
            let filtered = allProductData.map(item => 
              item.filter((val,index) => {
                if(selection.includes(index) && index > 3) {
                  return val;
                }
                })
            );
            console.log(filtered);
            filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));

            【讨论】:

            • filter() 期望返回一个布尔值,而不是元素值。这仅在这种情况下有效,因为所有字符串都是真实的。如果任何值是 0 或 null 或 NaN 等,则会中断。只需返回 includes() 语句
            • @charlietfl 实际单词不需要。如果条件为真,则返回 val。所以你是对的,这就是我相应编辑的原因,不需要返回 val;
            • 返回filter() 中的元素值是不正确的,因为它假定所有值都是真/假。你误解了整个观点。没必要粗鲁!!我所有的 cmets 都是建设性的,而不是侮辱性的
            • 你反应过度了......在过滤器中应该使用一些条件来返回一个布尔值......就是这样。这是它的记录方式以及如何避免不必要的副作用
            • @charlietfl 我想我提供的答案显示了很多。在我的皮肤下,除了肌肉、骨骼和血液,我什么都没有:)此外,我确实有自己的应用程序,其中一些不需要的值必须转到名为 emptybucket 并拥有所有上述评论中提到的值。在那种情况下,我会使用第二种方式,因为它更有效(对于所有这些情况返回相同的输出,检查上面的数字和布尔示例)。如果你不能理解这一点,那没问题。所以归根结底,这是一个很好的答案(如果你能看到的话)。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多