【问题标题】:How to make my JS solution functional?如何使我的 JS 解决方案发挥作用?
【发布时间】:2018-10-29 08:48:24
【问题描述】:

我有一些来自 Angular 的经典服务的数据,看起来像这样(简要地):

const obj = {
  field: [
    {
      id: 1,
      items: []
    },
    {
      id: 2,
      items: [ { wateva: 'wateva1' } ]
    },
    {
      id: 3,
      items: false
    },
    {
      id: 4,
      items: [ { yeah: 7 } ]
    }
  ] 
}

好吧,我的任务只是收集所有不为空的数组项。 我的解决方案(实际上我的解决方案是用 TypeScript 和 Angular 5 编写的,但为了让它更简单易懂,它会像......):

function getItems() {
  const items = [];

  obj.field.forEach(currentField => {
    if (currentField.items && currentField.items.length) {
      currentField.items.forEach(currentItem => items.push(currentItem));
    }
  });

  return items;
}

是的,它非常简单,并且可以按预期工作(当前的将返回...):

[ { wateva: 'wateva1' }, { yeah: 7 } ]

现在我的问题...如何使我的解决方案发挥作用?我想摆脱我的新变量items,我不想推入那个变量,我只想在一个动作中返回结果。任何帮助将不胜感激。

P.S.不接受第三图书馆的建议:)

【问题讨论】:

    标签: javascript arrays angular function functional-programming


    【解决方案1】:

    如果您可以使用 es6(并且由于您提到您使用的是 typescript,那应该没问题),您可以通过组合 concatmapfilter 将其变成一个很好的功能单行代码。和传播运算符:

    const obj = {
      field: [
        {
          id: 1,
          items: []
        },
        {
          id: 2,
          items: [ { wateva: 'wateva1' } ]
        },
        {
          id: 3,
          items: false
        },
        {
          id: 4,
          items: [ { yeah: 7 } ]
        }
      ] 
    }
    
    function getItems(obj) {
      return [].concat(...obj.field.map(o => o.items).filter(Array.isArray))
    }
    
    console.log(getItems(obj))

    【讨论】:

    • 好吧,显然我可以使用 es6 :) 谢谢你,伙计,这很棒,我很可怜 :)
    【解决方案2】:

    您可以使用flatMap (stage 3)flatMap 这里符合 Fantasy Land 的 chain 规范。

    data.field.flatMap
      (({ items }) =>
        Array.isArray (items) ? items : []
      )
    
    // [ { wateva: 'wateva1' }, { yeah: 7 } ]
    

    你可以在没有它的环境中填充它

    Array.prototype.flatMap = function (f) {
      return this.reduce
        ( (acc, x) =>
            acc.concat (f (x))
        , []
        )
    }
    

    完整程序演示

    Array.prototype.flatMap = function (f) {
      return this.reduce
        ( (acc, x) =>
            acc.concat (f (x))
        , []
        )
    }
    
    const data = 
      { field:
        [ { id: 1, items: [] }
        , { id: 2, items: [ { wateva: 'wateva1' } ] }
        , { id: 3, items: false }
        , { id: 4, items: [ { yeah: 7 } ] } 
        ]
      }
    
    const result =
      data.field.flatMap
        (({ items }) =>
          Array.isArray (items) ? items : []
        )
    
    console.log (result)
    // [ { wateva: 'wateva1' }, { yeah: 7 } ]

    【讨论】:

      【解决方案3】:

      您可以使用Array.reduce 和扩展运算符累积到一个空数组:

      obj.field.reduce(
          (acc, current) => current.items && current.items.length > 0 ? [...acc, ...current.items] : acc, [])
      );
      

      【讨论】:

        【解决方案4】:

        使用Array.prototype.reduceobject destructuring, and spread assignments

        function getItems({ field }) {
            return field.reduce((result, { items }) => 
                items instanceof Array ? 
                items.reduce((items, item) => [...items, item], result) :
                result
            , []);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多