使用ramda获取变量的升序/降序

cor*_*vid 0 javascript functional-programming ramda.js

我有一个要按名称排序的用户列表。该列表如下所示:

const data = [
  { id: 2, name: 'Asterios' },
  { id: 1, name: 'Alex' },
  { id: 4, name: 'Tim' },
  { id: 3, name: 'Sadie' },
]
Run Code Online (Sandbox Code Playgroud)

我实现了一个相对简单的选择器,该选择器将根据某些属性对用户列表进行排序。

const getUserList = createSelector(
  getUsers,
  getSortBy,
  getSortOrder,
  (users, sortBy, sortOrder) => R.sortWith([
    R.ascend(R.prop(sortBy)),
  ])(users),
);
Run Code Online (Sandbox Code Playgroud)

但是,我要使用sortOrder可以为'ASC'或的变量'DESC',并应用该排序顺序。

我尝试过这样的事情:

const sortDirection = R.ifElse(R.equals('DESC'), descend, ascend);

sortWith([ compose(sortDirection(sortOrder), prop('name')), ])
Run Code Online (Sandbox Code Playgroud)

是否有通过变量应用此升/降排序逻辑的好方法?

Sco*_*yet 5

好的,您这里有几个小问题。但是,调试一个大问题通常比几个小问题要容易。

ifElse正确使用

第一个是的使用ifElse。这将三个函数作为参数,并返回一个新函数,该函数根据使用参数调用第一个函数的结果,使用这些参数调用第二个或第三个函数。请注意,它不会返回该函数。它称之为。有几种方法可以解决此问题。您可以使用always

const sortDirection = R.ifElse(R.equals('DESC'), always(descend), always(ascend))
Run Code Online (Sandbox Code Playgroud)

但是我认为放弃免积分和使用更简单

const sortDirection = dir => (dir === 'DESC' ? descend : ascend)
Run Code Online (Sandbox Code Playgroud)

理解 compose

其次,您将一个稍微错误的值传递给ascenddescend。尽管这还不是完全的实现,但可以将其ascend视为

const ascend = curry(fn, a, b) => fn(a) < fn(b) ? -1 : fn(a) > fn(b) ? 1 : 0);
Run Code Online (Sandbox Code Playgroud)

请注意,如果将一元函数传递给该函数,例如fn = prop('name'),则会返回(a, b) => fn(a) < fn(b) ? -1 : fn(a) > fn(b) ? 1 : 0,它是一个二进制比较器函数。 sortWith接受比较器列表。所以这很好。

但是如果你sortOrder'ASC',那么这个

sortWith([ compose(sortDirection(sortOrder), prop('name')), ])
Run Code Online (Sandbox Code Playgroud)

变成

sortWith([ compose(ascend, prop('name')) ])
Run Code Online (Sandbox Code Playgroud)

相当于

sortWith([ x => ascend(prop('name')(x)) ])
Run Code Online (Sandbox Code Playgroud)

并且传递给排序器的函数不是正确的比较器。它是一元函数。问题在于这prop('name')是一元函数,因此与compose您希望的不一样。

如果您稍作重新排列,您将获得正确的行为:

sortWith([ compose(sortDirection(sortOrder), prop)('name'), ], )
Run Code Online (Sandbox Code Playgroud)

首先ASC,将转换为

sortWith([ compose(ascend, prop)('name'), ], )
Run Code Online (Sandbox Code Playgroud)

因此

sortWith([ (x => ascend(prop(x)))('name'), ], )
Run Code Online (Sandbox Code Playgroud)

这是

sortWith([ ascend(prop('name')), ], )
Run Code Online (Sandbox Code Playgroud)

如我们所见,ascend(fn)是一个二进制比较器。

把它放在一起

因此,解决问题的一种方法是

const sortDirection = R.ifElse(R.equals('DESC'), always(descend), always(ascend))
const sortOrder = 'DESC'
sortWith([ compose(sortDirection(sortOrder), prop)('name'), ], data)
//=> [{.. Tim}, {.. Sadie}, {.. Asterios}, {.. Alex}]
Run Code Online (Sandbox Code Playgroud)

当然,如果sortOrder = 'ASC',那么

sortWith([ compose(sortDirection(sortOrder), prop)('name'), ], data)
//=> [{.. Alex}, {.. Asterios}, {.. Sadie}, {.. Tim}]
Run Code Online (Sandbox Code Playgroud)

替代方法

关于上述内容,我仍然有两件事我真的不喜欢:

  1. 它使用free变量sortOrder。我希望此类变量是函数的参数。

  2. 它使用sortWith而不是sortsortWith组合比较器功能的一种方法。由于我们只有一个,sort所以比较简单。

这是解决这些问题的方法:

const sortDirection = R.ifElse(R.equals('DESC'), always(descend), always(ascend))
Run Code Online (Sandbox Code Playgroud)
const sortDirection = dir => (dir === 'DESC' ? descend : ascend)
Run Code Online (Sandbox Code Playgroud)