【问题标题】:Convert array to array of objects with reduce使用reduce将数组转换为对象数组
【发布时间】:2018-12-26 01:37:31
【问题描述】:
optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']

result = [
  {start: bengaluru, end: salem},
  {start: salem, end: erode},
  {start: erode, end: tiruppur},
  {start: tiruppur, end: coimbatore},
]

我想将optimizedRoute 转换为结果。我想用 ES6 .reduce() 做到这一点。这是我尝试过的:

const r = optimizedRoute.reduce((places, place, i) => {
  const result: any = [];
  places = []
  places.push({
    startPlace: place,
    endPlace: place
  });
  // result.push ({ startplace, endplace, seats: 4 });
  // console.log(result);
  return places;
}, {});
console.log(r)

【问题讨论】:

    标签: javascript arrays ecmascript-6


    【解决方案1】:

    ReduceRight 的解决方案,如果有人正在寻找的话。

    optimizedRoute.reduceRight((acc, d, i, arr) => 
                 i == 0 
                    ? acc 
                    : [{ start: arr[i -1], end: d }, ...acc]  
                , [])
    

    【讨论】:

    • 请解释为什么在这里投反对票,如果有人正在寻找使用 reduceRight 的解决方案(类似于 reduce),我添加了这个答案。谢谢。
    【解决方案2】:

    reduce 并不真正适合这里的账单,因为您并没有尝试将数组减少为单个值。

    在一个完美的世界中,我们应该有multi-array map version,通常称为zip,我们可以像这样使用它

    const result = zipWith(optimisedRoute.slice(0, -1),
                           optimisedRoute.slice(1),
                           (start, end) => ({start, end}));
    

    但在 JavaScript 中没有。最好的替代方法是使用Array.frommap 覆盖到路由的一系列索引中:

    const result = Array.from({length: optimisedRoute.length - 1}, (_, index) => {
         const start = optimisedRoute[index];
         const end = optimisedRoute[index + 1];
         return {start, end};
    });
    

    【讨论】:

    • 这种方法与 Mihai Alexandru-Ionut 和 Tom Fenech 所做的非常相似,您也应该为他们的答案投票!
    • @saila 糟糕,已修复。流程很简单,Array.from({length: …}, …) 是一个known trick,基本上等价于range(0, …).map(…)
    • @Bergi,按照 o 表示法是最好的。
    • @saila 我认为这里介绍的所有解决方案都有线性运行时间
    【解决方案3】:

    我更喜欢可读性,而不仅仅是解决它的短代码

    optimizedRoute.reduce((routes, city, index) => {
      const firstCity = index === 0;
      const lastCity = index === optimizedRoute.length - 1;
      if (!firstCity) {
        routes.last().end = city;
      }
      if (!lastCity) {
        routes.push({ start: city });
      }
      return routes;
    }, []);
    

    此外,该解决方案更短但可读性差(至少对我而言),可能是:

    optimizedRoute.reduce((routes, city) => {
      routes.last().start = city;
      routes.push({ end: city });
      return routes;
    }, [{}]).slice(1, -1);
    

    关于last(),这是我通常用于提高可读性的功能:

    Array.prototype.last = function() { 
      return this[this.length - 1] 
    }
    

    【讨论】:

      【解决方案4】:

      既然您要求reduce,这是一种方法:

      let optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
         
      let res = optimizedRoute.reduce((accum, item, i)=>{
         if(i == optimizedRoute.length - 1) 
            return accum;
         accum.push({start: item, end: optimizedRoute[i+1]})
         return accum;
      }, [])
      
      console.log(res);

      【讨论】:

        【解决方案5】:

        我不太明白“with reduce”的要求,因为使用循环的相应代码是立即可读的,不需要解释:

        const optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
        const result = new Array(optimizedRoute.length - 1);
        
        for (let i = 0; i < result.length; ++i) {
          result[i] = {
            start: optimizedRoute[i],
            end: optimizedRoute[i + 1]
          };
        }
        
        console.log(result)

        有时候做一些聪明的事情很有趣,但与此相比,有些答案非常复杂!

        【讨论】:

          【解决方案6】:

          我简化了 nina scholz 的答案, 按照 nina 的想法,使用 reduce 获取路径的开始和结束部分,并返回 end 用于下一次开始。

          getParts = a => {
            const result = [];
              a.reduce((start, end) => {
                result.push({ start, end });
                return end;
              });
              return result;
          };
          var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
          console.log(this.getParts(optimizedRoute));
          

          【讨论】:

            【解决方案7】:

            您可以使用reduce 获取路线的开始和结束部分,并返回结束以供下一次开始。

            getParts = a => (                   // take a as array and return an IIFE
                r => (                          // with an initialized result array
                    a.reduce((start, end) => (  // reduce array by taking two values
                        r.push({ start, end }), // push short hand properties
                        end                     // and take the last value as start value for next loop
                    )),
                    r                           // finally return result
                )
            )([]);                              // call IIFE with empty array
            

            const getParts = a => (r => (a.reduce((start, end) => (r.push({ start, end }), end)), r))([]);
            
            var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
            
            console.log(getParts(optimizedRoute));
            .as-console-wrapper { max-height: 100% !important; top: 0; }

            @EDIT Grégory NEUT 添加解释

            // Two thing to know first :
            
            // When no initial value is provided,
            // Array.reduce takes the index 0 as first value and start to loop at index 1
            
            // Doing (x, y, z)
            // Will execute the code x, y and z
            
            // Equivalent to :
            
            // x;
            // y;
            // z;
            
            let ex = 0;
            
            console.log((ex = 2, ex = 5, ex = 3));
            
            // So about the code
            
            const getParts = (a) => {
              // We are creating a new function here so we can have an array where to
              // push data to
              const func = (r) => {
                // Because there is no initial value
                //
                // Start will be the value at index 0 of the array
                // The loop is gonna start at index 1 of the array
                a.reduce((start, end) => {
                  console.log(start, end);
            
                  r.push({
                    start,
                    end,
                  });
            
                  return end;
                });
            
                return r;
              };
            
              return func([]);
            };
            
            // Equivalent
            const getPartsEquivalent = (a) => {
              const r = [];
            
              // Because there is no initial value
              //
              // Start will be the value at index 0 of the array
              // The loop is gonna start at index 1 of the array
              a.reduce((start, end) => {
                console.log(start, end);
            
                r.push({
                  start,
                  end,
                });
            
                return end;
              });
            
              return r;
            };
            
            var optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
            
            console.log(getPartsEquivalent(optimizedRoute));
            .as-console-wrapper {
              max-height: 100% !important;
              top: 0;
            }

            【讨论】:

            • 这令人印象深刻,但很难做到!
            • 尽管这可能是一个(好的)解决方案,但我认为这对于 OP 来说太难理解 OP 的给定技能了。
            • Nina,你能补充一些细节来解释这个很棒的单线的步骤吗?
            • @Nina Scholz 我不明白为什么第一个推送的值不是{ start: undefined, end: 'Bengaluru',} 。这是关于在没有初始值时忽略第一个值的减少吗?
            • @GrégoryNEUT,对,如果reduce不是以初始值开始的,那么前两个元素作为累加器和项目。索引以1 开头。为了说明,你可以试试这个:[4, 5, 6, 7].reduce((a, b, i) =&gt; (console.log(i, a, b), b));
            【解决方案8】:

            这是reduce 的示例。不过,我不确定这是最自然的方法!

            使用reduce 感觉有点矫枉过正,在这种情况下(但这只是我的看法),我自然会使用索引,好吧,我会选择一个简单的for 循环。

            const optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore'];
            let startCity;
            const result = optimizedRoute.reduce((acc, city) => {
              if(startCity) {
                acc.push({start: startCity, end: city});
              }
              startCity = city;
              return acc;
            }, []);
            
            console.log(result);

            【讨论】:

              【解决方案9】:

              以下代码使用Spread operatorTernary operatorArray.reduce

              const optimizedRoute = [
                'Bengaluru',
                'Salem',
                'Erode',
                'Tiruppur',
                'Coimbatore',
              ];
              
              // Look if we are at dealing with the last value or not
              // If we do only return the constructed array
              // If we don't, add a new value into the constructed array.
              
              // tmp is the array we are constructing
              // x the actual loop item
              // xi the index of the item
              const lastItemIndex = optimizedRoute.length - 1;
              
              const ret = optimizedRoute.reduce((tmp, x, xi) => xi !== lastItemIndex ? [
                ...tmp,
              
                {
                  start: x,
               
                  // We access to the next item using the position of
                  // the current item (xi)
                  end: optimizedRoute[xi + 1],
                },
              ] : tmp, []);
              
              console.log(ret);

              【讨论】:

                【解决方案10】:

                另一种方法是将map 方法与slice 结合使用。对于 map 函数,您必须将 callback 函数作为 argument 传递,它将应用于给定 array 中的每个项目。

                optimizedRoute = ['Bengaluru', 'Salem', 'Erode', 'Tiruppur', 'Coimbatore']
                var result = optimizedRoute
                                .slice(0, -1)
                                .map((item, index) => ({start : item, end : optimizedRoute[index + 1]}));
                console.log(result);

                【讨论】:

                  猜你喜欢
                  • 2021-12-27
                  • 2017-12-24
                  • 2023-03-14
                  • 2020-08-24
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-08-06
                  • 2021-11-08
                  相关资源
                  最近更新 更多