Javascript嵌套.map()返回多个数组

时间:2018-08-08 09:38:54

标签: javascript arrays filtering

鉴于我有一个JSON结构,如下所示:

{
    "firstData": [{
        "secondData": [{
            "thirdData": [{
                "value": "whatever"
            }]
        }]
    }]
}

我需要从thirdData value === "whatever"来映射

所以我在做

 const result = firstData.map(first => {
            return first.secondData.map(second => {
                return second.thirdData.map(third => {
                    return third.value === 'whatever';
                });
            });
        });

这工作得很好,但是结果是另一个深度嵌套的数组(如[ [ [ {results..} ] ] ])。我知道我可以通过其他方法将其展平为单个数组,但是我觉得我很想念{{ 1}}。如何将该结果修改为包含.map()值的单个数组,而该值就是我想要的值?

所需的结果将是thirdData个对象的单个数组:

thirdData

2 个答案:

答案 0 :(得分:2)

如果您希望获得统一的结果,那么这不是map的用例。简单的解决方案是使用关闭的数组并推送至:

const result = [];
firstData.forEach(first => {
    return first.secondData.forEach(second => {
        result.push(...second.thirdData.filter(third => third.value === 'whatever'));
    });
});

在线示例,对您提供的最少数据进行了少许扩展:

const data = {
    "firstData": [{
            "secondData": [{
                "thirdData": [{
                        "value": "whatever",
                        "label": "third #1.1"
                    },
                    {
                        "value": "whatever",
                        "label": "third #1.2"
                    },
                    {
                        "value": "unrelated",
                        "label": "unrelated"
                    }
                ]
            }]
        },
        {
            "secondData": [{
                "thirdData": [{
                        "value": "another unrelated"
                    },
                    {
                        "value": "whatever",
                        "label": "third #2"
                    }
                ]
            }]
        }
    ]
};
const result = [];
data.firstData.forEach(first => {
    return first.secondData.forEach(second => {
        result.push(...second.thirdData.filter(third => third.value === 'whatever'));
    });
});
console.log(result);
.as-console-wrapper {
  max-height: 100% !important;
}

请注意filter上的thirdData,并使用扩展符号将数据推送到result

假定您要从thirdData中输入具有.value === 'whatever'而不是true / false的条目。如果您希望使用true / false,请将filter更改为map

或等效于for-of

const result = [];
for (const first of firstData) {
    for (const second of first.secondData) {
        result.push(...second.thirdData.filter(third => third.value === 'whatever'));
    }
}

在线示例,对您提供的最少数据进行了少许扩展:

const data = {
    "firstData": [{
            "secondData": [{
                "thirdData": [{
                        "value": "whatever",
                        "label": "third #1.1"
                    },
                    {
                        "value": "whatever",
                        "label": "third #1.2"
                    },
                    {
                        "value": "unrelated",
                        "label": "unrelated"
                    }
                ]
            }]
        },
        {
            "secondData": [{
                "thirdData": [{
                        "value": "another unrelated"
                    },
                    {
                        "value": "whatever",
                        "label": "third #2"
                    }
                ]
            }]
        }
    ]
};
const result = [];
for (const first of data.firstData) {
    for (const second of first.secondData) {
        result.push(...second.thirdData.filter(third => third.value === 'whatever'));
    }
}
console.log(result);
.as-console-wrapper {
  max-height: 100% !important;
}

(关于filter / map的相同说明。)

与所有数组操作一样,您可以将其塞入reduce,并且我保证您将主要使用reduce得到答案,但是这里没有充分的理由使用reduce

const result = firstData.reduce((result, first) => {
    return first.secondData.reduce((result, second) => {
        result.push(...second.thirdData.filter(third => third.value === 'whatever'));
        return result;
    }, result);
}, []);

尽管如此,没有充分的理由。只是更加复杂。

在线示例,对您提供的最少数据进行了少许扩展:

const data = {
    "firstData": [{
            "secondData": [{
                "thirdData": [{
                        "value": "whatever",
                        "label": "third #1.1"
                    },
                    {
                        "value": "whatever",
                        "label": "third #1.2"
                    },
                    {
                        "value": "unrelated",
                        "label": "unrelated"
                    }
                ]
            }]
        },
        {
            "secondData": [{
                "thirdData": [{
                        "value": "another unrelated"
                    },
                    {
                        "value": "whatever",
                        "label": "third #2"
                    }
                ]
            }]
        }
    ]
};
const result = data.firstData.reduce((result, first) => {
    return first.secondData.reduce((result, second) => {
        result.push(...second.thirdData.filter(third => third.value === 'whatever'));
        return result;
    }, result);
}, []);
console.log(result);
.as-console-wrapper {
  max-height: 100% !important;
}

(关于filter / map的相同说明。)

答案 1 :(得分:2)

您可以使用Array#reduce简化为单个值(在本例中为单个数组),并使用Array#forEach迭代嵌套数组。

const data = {
  "firstData": [{
    "secondData": [{
      "thirdData": [{
        "value": "whatever"
      }]
    }]
  }]
}

const result = data.firstData.reduce((arr, first) => {
  // iterate over the second level array
  first.secondData.forEach(second => {
    // iterate over the third level array
    second.thirdData.forEach(third => {

      // push the value into the result array,
      // change here, in case you want the value 
      //arr.push(third.value === 'whatever');
      
      // in case you need the object then do it like
      if(third.value === 'whatever') arr.push(third);

    });
  });
  // return the array reference for the next iteration
  return arr;

  // set the initial value as an array for the result
}, []);

console.log(result);