Как сделать мое решение JS функциональным? - PullRequest
0 голосов
/ 19 мая 2018

У меня есть некоторые данные из классного сервиса в 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 , я не хочу вставлять эту переменную, я просто хочу вернуть результат одним действием.Мы будем благодарны за любую помощь.

PS Предложения с третьими библиотеками не принимаются:)

Ответы [ 4 ]

0 голосов
/ 19 мая 2018

Вы можете использовать flatMap (этап 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 } ]
0 голосов
/ 19 мая 2018

Вы можете использовать Array.reduce и оператор распространения для накопления в пустом массиве:

obj.field.reduce(
    (acc, current) => current.items && current.items.length > 0 ? [...acc, ...current.items] : acc, [])
);
0 голосов
/ 19 мая 2018

Использование Array.prototype.reduce , деструктуризация объектов и присвоение спредов :

function getItems({ field }) {
    return field.reduce((result, { items }) => 
        items instanceof Array ? 
        items.reduce((items, item) => [...items, item], result) :
        result
    , []);
}
0 голосов
/ 19 мая 2018

Если вы можете использовать es6 (и поскольку вы упомянули, что вы используете машинописный текст, это должно быть хорошо), вы можете превратить это в хороший функциональный однострочный, комбинируя concat, map, filter,и оператор распространения:

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...