【问题标题】:Split element into array with reduce()使用 reduce() 将元素拆分为数组
【发布时间】:2016-12-20 13:21:17
【问题描述】:

我在图中有一些边,我得到了:

const edges = getEdges();

每条边都有一个标签数组,我得到了:

const edges = getEdges().map(function (edge, i) {
  return (i + 1) + '-' + getLabels(edge).sort().join('-');
});

所以如果我有 2 条边,每条边都有两个标签,我会得到一个数组

[
  '1-label1-label2',
  '2-label1-label2'
]

但我想要的是

[
  '1-label1',
  '2-label2',
  '3-label1',
  '4-label2'
]

所以我想我需要使用Array.reduce()

【问题讨论】:

  • 这是什么逻辑?我们可以举个边的例子吗?

标签: javascript arrays ecmascript-6 reduce


【解决方案1】:

使用Array#reduce 方法做这样的事情。

const edges = getEdges().reduce(function(arr, edge) {
  return arr.concat(
    getLabels(edge)
    .sort()
    .map(function(v, i) {
      return (arr.length + i) + '-' + v;
    })
  );
}, []);

使用Array#push 方法代替Array#concat 方法。

const edges = getEdges().reduce(function(arr, edge) {
  [].push.apply(arr, getLabels(edge)
    .sort()
    .map(function(v, i) {
      return (arr.length + i) + '-' + v;
    })
  );
  return arr;
}, []);

【讨论】:

    【解决方案2】:

    在我看来,mapreduce 都不是您真正想要的,只是一对嵌套的 forEach(尽管如果我们愿意,我们可以将 reduce 插入其中):

    const edges = [];
    getEdges().forEach(edge => {
      getLabels(edge).sort().forEach(label => {
        edges.push(`${(edges.length + 1)}-${label}`);
      });
    });
    

    现场示例:

    const getEdges = () =>
      [
        {labels: ['label2', 'label1']},
        {labels: ['label1', 'label2']}
      ];
    const getLabels = edge => edge.labels;
    
    const edges = [];
    getEdges().forEach(edge => {
      getLabels(edge).sort().forEach(label => {
        edges.push(`${(edges.length + 1)}-${label}`);
      });
    });
    console.log(edges);

    【讨论】:

      【解决方案3】:

      您可以先将getEdges 的结果映射到getLabels,然后使用Array.prototype.concat 和展开语法将结果数组展平。

      const getEdges = () => ['a', 'b'];
      const getLabels = () => ['label1', 'label2'];
      
      const edges = [].concat(...getEdges().map(getLabels))
        .map((label, i) => `${i + 1}-label`);
      console.log(edges);

      【讨论】:

        【解决方案4】:

        您可以使用forEach 代替mapreduce,如下所示。

        工作 sn-p:(ES6)

        const getEdges = () => [
             '1-label1-label2',
             '2-label1-label2'
           ];
        
        const getLabels = (edge) => edge.split('-').sort();
        
        let edges = [];
        
        getEdges().forEach((edge) => {
          getLabels(edge).forEach((label) => {
            if(label.indexOf('label') > -1) {
               edges.push(edges.length + 1 + '-' + label);
            }
          });
        });
        
        console.log(edges);

        工作 sn-p:(ES5)

        function getEdges() {
           return [
             '1-label1-label2',
             '2-label1-label2'
           ];
        }
        
        function getLabels(edge) {
          return edge.split('-').sort();
        }
        
        var edges = [];
        
        getEdges().forEach(function (edge) {
          getLabels(edge).forEach(function (label) {
            if(label.indexOf('label') > -1) {
               edges.push(edges.length + 1 + '-' + label);
            }
          });
        });
        
        console.log(edges);

        【讨论】:

          【解决方案5】:

          您可以在边上使用 reduce 操作,它获取每条边并添加到新构造的数组中。

          在每条边的标签上使用 forEach 会产生 1..n 个项目,这些项目将被添加到这个新数组中。使用新数组(结果)的当前长度可以巧妙地解决根据需要(即从 1 到 N)命名结果项的问题。

          const res = getEdges().reduce(result, edge => {
            const labels = getLabels(edge).sort();
            labels.forEach(label => result.push(`${result.length + 1}-${label}`));
            return result;
          }, []);
          

          注意:此解决方案使用 reduce 和 ES6 功能,这是根据提到的标签。

          【讨论】:

          • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
          • 补充说明
          猜你喜欢
          • 1970-01-01
          • 2014-03-02
          • 1970-01-01
          • 1970-01-01
          • 2017-07-30
          • 2015-04-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多