如何一起提升和组合功能?

时间:2019-05-18 19:09:14

标签: javascript functional-programming lodash ramda.js lifting

我有一个这样的人名单:

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中的Predicatelifted,如下所示:

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 Boolean get curry not并编写withFriends和{ {1}}的Array.filter谓词在withOutFriends的列表上。

回复:https://repl.it/@matthewharwood/ChiefWelloffPaintprogram

people

1 个答案:

答案 0 :(得分:2)

由于具有/不具有好友功能的结果是布尔值,因此您可以取反(或取反)其中一个的结果以得到另一个。另外,这些功能的偶数为1(它们对其进行操作的对象)。

Lodash / fp:

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>

Ramda:

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. flow / pipe / compose中的第一个函数获取传递给组合函数的所有内容。序列中的其他函数始终获得单个参数(上一个函数的结果)/。
  3. Ramda和Lodash都具有拒绝方法,该方法与filter相反,如果谓词返回true,则该项目将被删除。例如,R.reject(foo, xs)等效于R.filter(R.complement(foo), xs)。 (在此comment中由@ScottSauyet指出)