Как поднять и составить функции вместе? - PullRequest
1 голос
/ 18 мая 2019

У меня есть список людей в этой структуре:

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];

Я бы хотел отфильтровать людей двумя способами: с друзьями и без друзей; Более того, я бы хотел, чтобы Предикат из Array.filter был поднял , вот так:

const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);

const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

Я могу добиться такого поведения, явно написав by функцию, подобную этой:

const by = x => i => {
  return Boolean(get(i, x));
};
const withFriends = by('friends.length');
const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

Проблема: Если бы я хотел обратное, мне нужно было бы явно написать совершенно новую функцию для peopleWithoutFriends

const notBy = x => i => {
  return !Boolean(get(i, x));
};

const withOutFriends = notBy('friends.length');
const peopleWithoutFriends = people.filter(withOutFriends);

Я не хочу писать свою функцию by дважды. Я бы предпочел сочинять меньшие функции вместе.

Вопрос:

Как написать и использовать небольшие функции, такие как: flow Booleanget curry not и составьте withFriends и withOutFriends Предикаты для моего Array.filter по списку people.

Repl: https://repl.it/@matthewharwood/ChiefWelloffPaintprogram

const {flow, get, curry} = require('lodash');

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];
const not = i => !i;

const withFriends = i => flow(
  Boolean,
  get(i, 'friends.length'), // arity of this is 2 so might be harder to lift, is it possible tho with curry?
); // No idea what i'm doing here.


const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

const withoutFriends = flow(not, withFriends);
const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);

1 Ответ

2 голосов
/ 18 мая 2019

Поскольку результатом функции с / без друзей является логическое значение, вы можете аннулировать (или дополнить) результат одного, чтобы получить другой.Кроме того, арность функций равна 1 (объект, над которым они работают).

Лодаш / фп:

const { flow, get, isEmpty, negate } = _;

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];

const withoutFriends = flow(get('friends'), isEmpty); // create a function that gets the friends array, and check if it is empty
const withFriends = negate(withoutFriends); // negate the result of withoutFriends

const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

Рамда:

const { pipe, prop, isEmpty, complement } = R;

const people = [
  {name: 'jenny', friends: ['jeff']},
  {name: 'frank', friends: ['jeff', 'ross']},
  {name: 'sarah', friends: []},
  {name: 'jeff', friends: ['jenny', 'frank']},
  {name: 'russ', friends: []},
  {name: 'calvin', friends: []},
  {name: 'ross', friends: ['frank']},
];

const withoutFriends = pipe(prop('friends'), isEmpty); // create a function that gets the friends array, and check if it is empty
const withFriends = complement(withoutFriends); // negate the result of withoutFriends

const peopleWithFriends = people.filter(withFriends);
console.log(peopleWithFriends);

const peopleWithoutFriends = people.filter(withoutFriends);
console.log(peopleWithoutFriends);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

Примечания:

  1. Оба _.flow() и R.pipe выполняют последовательность слева направо (сверху вниз).Порядок функций _.compose() и R.compose меняется на обратный.
  2. 1-я функция в потоке / трубе / компоновке получает все, что передано составной функции.Другие функции в последовательности всегда получают один параметр (результат предыдущей функции) /.
  3. И у Рамды, и у Лодаша есть метод отклонения, который противоположен фильтру, если предикат возвращает trueТовар удален.Например, R.reject(foo, xs) эквивалентно R.filter(R.complement(foo), xs).(замечено @ ScottSauyet's в этом комментарии )
...