Меня поражает, что это вызывает какой-то более чистый, лучше продуманный код. Я представляю себе решение, которое выглядит примерно так:
const transform = combine (
uniqueBy (sameProp ('settlementCode') ),
filter (not (propMatches ('settlementDesc', ['not covered', 'invalid quantity'])))
)
Что будут делать все эти вспомогательные функции?
Идея состоит в том, что combine
будет принимать две функции и возвращать новую, которая передает выходные данные одной в другую. Для этого есть стандартное имя, compose
, так что я бы на самом деле выбрал.
sameProp('foo')
примет два объекта и скажет, имеют ли они равные foo
свойства. Так что sameProp
примет имя свойства и вернет этот двоичный предикат. (Предикат - это просто функция, которая возвращает true
или false
)
uniqueBy
будет принимать двоичный предикат и список и удалять все дубликаты на основе этого предиката, сохраняя только первый.
filter
просто повысит Array.prototype.filter
до автономной функции.
propMatches
будет принимать имя свойства и список строк, возвращая функцию, которая принимает объект, и сообщая, является ли свойство names этого объекта совпадением с регулярным выражением для одной из этих строк.
И, наконец, not
просто примет предикат и вернет второй, который возвращает false
, если начальный возвращает true
и true
, если он вернет false
. (В качестве альтернативы он может называться invert
, opposite
или complement
.)
Вот реализация этого:
const compose = (f, g) =>
(x) => f(g(x))
const filter = (fn) => (xs) =>
xs.filter(fn)
const not = (f) =>
(x) => !f(x)
const sameProp = (prop) => (a, b) =>
a [prop] === b [prop]
const uniqueBy = (pred) => (xs) =>
xs .filter ( (x, i) => xs .findIndex (y => pred (x, y) ) == i )
const propMatches = (prop, vals, re = new RegExp (vals .join ('|'), 'i') ) =>
(x) => !! re .test ( x [prop] )
const transform = compose (
uniqueBy (sameProp ('settlementCode')),
filter (not (propMatches ('settlementDesc', ['not covered', 'invalid quantity'])))
)
const messages = [{settlementCode: "58", settlementDesc: "Not Covered Needs prior authorization: System could not process your request. Call us at the toll-free number on your benefit ID card."}, { settlementCode: "58", settlementDesc: "Not Covered Needs prior authorization: System could not process your request. Call us at the toll-free number on your benefit ID card."}, { settlementCode: "359", settlementDesc: "Needs prior authorization: System could not process your request. Call us at the toll-free number on your benefit ID card."}]
console .log (
transform (messages)
)
Обратите внимание, что вспомогательные функции, особенно первые четыре, являются чрезвычайно простыми функциями. Все они (за исключением, может быть, propMatches
) кода, который, вероятно, можно повторно использовать во многих частях приложения. Таким образом, они могут быть размещены в вашей внутренней служебной библиотеке, оставляя только transform
(и снова, возможно, propMatches
) как часть реализации этого требования.
Есть и другие вещи, которые вы могли бы сделать с ними. Мы можем легко представить версию compose
, которая принимает любое количество функций, или версию, которая принимает их в обратном порядке. Мы могли бы также представить, что мы можем захотеть передать больше одного параметра в функцию, которая получается из него. Но мы можем добавить такие улучшения позже, когда они нам действительно понадобятся.
В качестве альтернативы, мы можем использовать служебную библиотеку, которая предоставляет такие функции. Я один из авторов Ramda , и эта библиотека поставляет (расширенную) compose
, версию sameProp
, которая называется eqProps
, немного по-другому uniqBy
, filter
и версия not
под названием complement
. Для меня постоянная доступность этих полезных функций значительно упрощает кодирование.