我有一个我想按名称排序的用户列表。列表看起来像这样:
const data = [
{ id: 2, name: 'Asterios' },
{ id: 1, name: 'Alex' },
{ id: 4, name: 'Tim' },
{ id: 3, name: 'Sadie' },
]
我已经实现了一个相对简单的选择器,它将根据某些属性对用户列表进行排序。
const getUserList = createSelector(
getUsers,
getSortBy,
getSortOrder,
(users, sortBy, sortOrder) => R.sortWith([
R.ascend(R.prop(sortBy)),
])(users),
);
但是,我想采用变量sortOrder
,可以是'ASC'
或'DESC'
,并应用该排序顺序。
我试过这样的事情:
const sortDirection = R.ifElse(R.equals('DESC'), descend, ascend);
sortWith([ compose(sortDirection(sortOrder), prop('name')), ])
是否有通过变量应用此升序/降序排序逻辑的好方法?
答案 0 :(得分:4)
好的,这里有几个小问题。但是,调试一个大问题通常比几个小问题更容易。
ifElse
第一个是使用ifElse
。这需要三个函数作为参数,并返回一个新函数,根据使用您的参数调用第一个函数的结果,调用使用这些参数的第二个或第三个函数。请注意,它不会返回该功能;它称之为。有几种方法可以解决这个问题。您可以使用always
包装这些函数:
const sortDirection = R.ifElse(R.equals('DESC'), always(descend), always(ascend))
但我认为放弃无点并使用
更简单const sortDirection = dir => (dir === 'DESC' ? descend : ascend)
compose
其次,您将稍微错误的值传递给ascend
或descend
。虽然这不是一个完整的实现,但请将ascend
视为
const ascend = curry(fn, a, b) => fn(a) < fn(b) ? -1 : fn(a) > fn(b) ? 1 : 0);
请注意,如果您将一元函数传递给此函数(例如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')), ])
变为
sortWith([ compose(ascend, prop('name')) ])
相当于
sortWith([ x => ascend(prop('name')(x)) ])
传递给分拣机的功能不是一个合适的比较器。这是一个一元的功能。问题是prop('name')
是一元函数,因此compose
并不能达到你所希望的效果。
如果你稍微重新安排,你可以得到正确的行为:
sortWith([ compose(sortDirection(sortOrder), prop)('name'), ], )
首先将ASC
转换为
sortWith([ compose(ascend, prop)('name'), ], )
因此
sortWith([ (x => ascend(prop(x)))('name'), ], )
是
sortWith([ ascend(prop('name')), ], )
正如我们所见,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}]
当然,如果是sortOrder = 'ASC'
,那么
sortWith([ compose(sortDirection(sortOrder), prop)('name'), ], data)
//=> [{.. Alex}, {.. Asterios}, {.. Sadie}, {.. Tim}]
有两件事我还是不喜欢上面的事情:
它使用自由变量sortOrder
。我希望这些变量是我的函数的参数。
它使用sortWith
而不是sort
。 sortWith
是一种组合比较器功能的方法。由于我们只有一个,sort
更简单。
以下是我如何编写它来解决这些问题:
const {ascend, descend, prop, sort} = R
const data = [{ id: 2, name: 'Asterios' }, { id: 1, name: 'Alex' }, { id: 4, name: 'Tim' }, { id: 3, name: 'Sadie' }]
const sorter = dir => (dir === 'DESC' ? descend : ascend)(prop('name'))
console.log(sort(sorter('DESC'), data))
//=> [{.. Tim}, {.. Sadie}, {.. Asterios}, {.. Alex}]
console.log(sort(sorter('ASC'), data))
//=> [{.. Alex}, {.. Asterios}, {.. Sadie}, {.. Tim}]
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
&#13;
答案 1 :(得分:2)
这不使用Ramda,但希望它可以让您了解如何开始解决问题
const ascComparator = (a, b) =>
a < b
? -1
: a > b
? 1
: 0
const descComparator = (a, b) =>
ascComparator (b, a)
const data =
[ { id: 2, name: 'Asterios' }
, { id: 1, name: 'Alex' }
, { id: 4, name: 'Tim' }
, { id: 3, name: 'Sadie' }
]
data.sort ((a,b) => ascComparator (a.name, b.name))
console.log (data)
// Alex, Asterios, Sadie, Tim
data.sort ((a,b) => descComparator (a.name, b.name))
console.log (data)
// Tim, Sadie, Asterios, Alex
上面的程序演示了contramap
const contramap = (f, g) =>
(a, b) =>
f (g (a), g (b))
const prop = k => o =>
o [k]
const ascComparator = (a, b) =>
a < b
? -1
: a > b
? 1
: 0
const descComparator = (a, b) =>
ascComparator (b, a)
const data =
[ { id: 2, name: 'Asterios' }
, { id: 1, name: 'Alex' }
, { id: 4, name: 'Tim' }
, { id: 3, name: 'Sadie' }
]
data.sort (contramap (ascComparator, prop ('name')))
console.log (data)
// Alex, Asterios, Sadie, Tim
data.sort (contramap (descComparator, prop ('name')))
console.log (data)
// Tim, Sadie, Asterios, Alex
localeCompare
也有效
const ascComparator = (a, b) =>
a.localeCompare (b)
const descComparator = (a, b) =>
ascComparator (b, a)