2016-10-11 37 views
2

我仍然对这些方法感兴趣。 我有一组嵌套的数组,我需要从中提取美国,目前我有这样的:array mapped,reduce,filter

// For each group 
groups.forEach(function (group) { 

    // For each question 
    group.questions.forEach(function (question) { 

     // For each answer 
     question.answers.forEach(function (answer) { 

      // For each state 
      answer.states.forEach(function (state) { 

       // Push to our array 
       states.push(state); 
      }); 
     }); 
    }); 
}); 

我相信我能做到这一点与新阵列方法更好的方法提供给我。 有人可以帮我一把,让我知道哪一个?

+0

迭代而改变它的内容一脸尴尬这里。 – Redu

+0

看起来你正朝着正确的方向前进!看看[这个函数式编程页面](http://reactivex.io/learnrx/).. –

+0

你可以给你一个你正在使用的数组的简短范例吗?这样我们就可以看到您正在使用的输入('groups'数组),并且您可以向我们展示您期望的确切输出(来自该示例数据)。这使我们能够提供更具体的实用建议,而不是试图猜测。 –

回答

0

一种方法是使用一系列reduce操作。

groups.reduce((arr, group) => arr.concat(group.questions), []) 
     .reduce((arr, question) => arr.concat(question.answers), []) 
     .reduce((arr, answer) => arr.concat(answer.states), []) 

这是功能上等同于原来的解决方案,我在下面的代码片段证明:

var groups = [{ 
 
    questions: [{ 
 
    answers: [{ 
 
     states: [ 
 
     1, 
 
     2, 
 
     3 
 
     ] 
 
    }, { 
 
     states: [ 
 
     4, 
 
     5, 
 
     6 
 
     ] 
 
    }] 
 
    }, { 
 
    answers: [{ 
 
     states: [ 
 
     7, 
 
     8, 
 
     9 
 
     ] 
 
    }, { 
 
     states: [ 
 
     10, 
 
     11, 
 
     12 
 
     ] 
 
    }] 
 
    }] 
 
}, { 
 
    questions: [{ 
 
    answers: [{ 
 
     states: [ 
 
     13, 
 
     14, 
 
     15 
 
     ] 
 
    }, { 
 
     states: [ 
 
     16, 
 
     17, 
 
     18 
 
     ] 
 
    }] 
 
    }, { 
 
    answers: [{ 
 
     states: [ 
 
     19, 
 
     20, 
 
     21 
 
     ] 
 
    }, { 
 
     states: [ 
 
     22, 
 
     23, 
 
     24 
 
     ] 
 
    }] 
 
    }] 
 
}]; 
 

 
function yourMethod() { 
 
    var states = []; 
 
    // For each group 
 
    groups.forEach(function (group) { 
 
    // For each question 
 
    group.questions.forEach(function (question) { 
 
     // For each answer 
 
     question.answers.forEach(function (answer) { 
 
     // For each state 
 
     answer.states.forEach(function (state) { 
 
      // Push to our array 
 
      states.push(state); 
 
     }); 
 
     }); 
 
    }); 
 
    }); 
 
    return states; 
 
} 
 

 
function myMethod() { 
 
    return groups.reduce((arr, group) => arr.concat(group.questions), []) 
 
       .reduce((arr, question) => arr.concat(question.answers), []) 
 
       .reduce((arr, answer) => arr.concat(answer.states), []); 
 
} 
 

 
var originalResult = yourMethod(); 
 
var newResult = myMethod(); 
 
console.log(originalResult.join(' ') === newResult.join(' '));

+0

恕我直言,像这样的'.reduce()'的大多数用法更适合CodeGolf而不是SO。重复'concat'使其成为N^2算法,因为每个级联必须复制两个数组。 – Barmar

+0

@Barmar绝对正确。我想我应该指出,我觉得这更容易阅读,但它绝对是低效的。 –

0

,你可以,如果你处理阵列就像一个纯数组使用递归性这个:

var result = []; 
var seek = arr => { 
    if (Array.isArray(arr)) arr.forEach(subArray => seek(subArray)); 
    else result.push(arr); 
} 
seek(groups) 
console.log (result) 
0

我个人认为你的方法是最可读的方法。其他方法可以缩短,但通常很难阅读。

无论如何,如果您仍然需要更清洁的解决方案,我建议您使用ES6来缩短语法。

for(let group of groups){ 
    for(let question of group.questions){ 
    for(let answer of question.answers){ 
     states.push(...answer.states); 
    } 
    } 
} 
+0

请注意,“for-of”在许多仍然很常见的浏览器中不可用。 – Barmar

0

有点offtopic,但你可以使用map_.flattenDeep组合从lodash:对`states`阵列

_.flattenDeep(groups.map(g => g.questions.map(q => q.answers.map(a => a.states))));