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)
是否有通过变量应用此升/降排序逻辑的好方法?
好的,您这里有几个小问题。但是,调试一个大问题通常比几个小问题要容易。
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其次,您将一个稍微错误的值传递给ascend或descend。尽管这还不是完全的实现,但可以将其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)
关于上述内容,我仍然有两件事我真的不喜欢:
它使用free变量sortOrder。我希望此类变量是函数的参数。
它使用sortWith而不是sort。 sortWith是组合比较器功能的一种方法。由于我们只有一个,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)