[英]Sort with ramda
我处于需要按名称对对象数组进行排序的情况。
Array = [
{id: 3d4, name: A2},
{id: 7b2, name: A1+ Beta},
{id: 9h5, name: A2 Beta},
{id: 1x1, name: A1+}
]
如何使用 Ramda 按此顺序对其进行排序:
我已经考虑过按名称长度拆分然后排序,但我坚持下去。 有人可以帮我弄这个吗?
Found on documentation of Ramda, is pretty simple, you create your filtering function with something like: const sortByNameCaseInsensitive = R.sortBy(R.compose(R.toLower, R.prop('name')));
然后你在其中应用你的数组sortByNameCaseInsensitive(arr);
您可以尝试 Reversing R.reverse
将数组拆分后使用new RegExp('[+]?\\s')
。
const array = [ {id: '3d4', name: 'A2'}, {id: '9hh', name: 'A3 Beta'}, {id: '7b2', name: 'A1+ Beta'}, {id: '9h5', name: 'A2 Beta'}, {id: '1x1', name: 'A1+'}, {id: '1x2', name: 'A3+'} ]; // pick name and convert to lowercase if required. const namePropCompose = R.compose(R.toLower, R.prop('name')); // split by '+ ' or ' ' and reverse the array. const splitNameAndReverse = R.compose(R.reverse, R.split(new RegExp('[+]?\\s'))); // finally sort with reversed array const sortByNameCaseInsensitive = R.sortBy(R.compose(splitNameAndReverse, namePropCompose)); const result = sortByNameCaseInsensitive(array); console.log(JSON.stringify(result))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js" integrity="sha512-rZHvUXcc1zWKsxm7rJ8lVQuIr1oOmm7cShlvpV0gWf0RvbcJN6x96al/Rp2L2BI4a4ZkT2/YfVe/8YvB2UHzQw==" crossorigin="anonymous"></script>
为了更好的可读性,我将它们全部分成不同的组合。 正则Regex and toLower
在这里可能没那么有用,简而言之,如果你愿意,你可以在一行中完成所有这些。
sortBy(compose(reverse, split(' '), prop('name')))
我认为['A1+', 'A2', 'A1+ Beta', 'A2 Beta']
排名足够随意,可能会建议手动排序他们的优先级。
scores
数组中找到每个rank
的position
a - b
const scores = ['A1+', 'A2', 'A1+ Beta', 'A2 Beta']; const findScorePriority = R.pipe( R.prop('name'), R.equals, R.findIndex(R.__, scores), ); const byPriority = R.useWith( R.subtract, [findScorePriority, findScorePriority], ); const data = [ { id: '3d4', name: 'A2' }, { id: '7b2', name: 'A1+ Beta' }, { id: '9h5', name: 'A2 Beta' }, { id: '1x1', name: 'A1+' }, ]; console.log( R.sort(byPriority, data), );
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>
从您的示例中不清楚您的排序顺序是基于简单的固定列表还是您没有提供足够的示例来演示一般原则。 如果是前者,那么hitmands 所描述的技术的一些变体就是你想要的。
在这里,我们假设您希望按name
字段的前半部分( 'A1+'
、 'A2'
等)进行主要排序,如果存在后半部分(例如'Beta'
)进行次要排序。
我们可以在 vanilla JS 中轻松编写,如下所示:
const customSort = (array) =>
[...array] .sort ((
{name: a}, {name: b},
[a0, a1 = ''] = a.split(' '), [b0, b1 = ''] = b.split(' ')
) =>
a0 < b0 ? -1 : a0 > b0 ? 1 : a1 < b1 ? -1 : a1 > b1 ? 1 : 0
)
Ramda 提供了原生Array.prototype.sort
没有的两件事:首先,它使用函数而不是方法,因此更容易与其他函数组合。 其次,它是非破坏性的。 Ramda 排序函数不会改变数组,而是返回它的排序副本。
Ramda 提供了三个主要的函数来处理排序。 首先是sort
,类似于:
const sort = (comp) => (array) =>
[... array] .sort (comp)
然后是sortBy
,它将 function 从数组中的元素转换为某种有序类型( String
、 Number
、 Date
、 {valueOf}
),并根据 function 的结果对数组进行升序排序。
还有sortWith
,它很像sortBy
,但需要一个这样的函数数组,所以如果前两个根据第一个 function 并列,那么我们用第二个进行测试,依此类推。
有三个辅助函数, descend
和它稍微多余的双胞胎 raise ,它们采用相同类型的ascend
传递给sortBy
或sortWith
并返回适合传递给sort
或Array.prototype.sort
的 function 。 我们可以像这样使用它们:
const oldestFirst = sort (descend (prop ('age')))
// ...
const reordered = oldestFirst (people)
或喜欢
people .sort (descend (prop('age')) // WARNING: mutates `people`
我们有comparator
,它将报告第一项是否小于第二项的二进制谓词转换为比较器 function 再次适用于sort
或Array.prototype.sort
。
因为我们想要一个两级排序,所以sortWith
是合适的。 我们可以像这样使用ascend
helper来编写它:
const customSort = sortWith ([
ascend (({name}) => name .split (' ') [0]),
ascend (({name}) => name .split (' ') [1] || ''),
])
虽然我对此很满意,但有些人更喜欢完全无点,在这种情况下并不太难:
const customSort = sortWith ([
ascend (pipe (prop ('name'), split (' '), prop(0))),
ascend (pipe (prop ('name'), split (' '), propOr('', 1)))
])
这些方法在我看来比香草版本更具可读性。 我看到他们唯一的缺点是他们需要为每次比较调用split
两次,而 vanilla 版本只能调用一次。 正因为如此,并且由于额外的 function 调用,它们的性能肯定会低于香草版本,但我希望它们对于许多用途来说足够快。
您可以在此代码段中看到所有这些选项:
const customSort1 = (array) => [...array].sort (( {name: a}, {name: b}, [a0, a1 = ''] = a.split(' '), [b0, b1 = ''] = b.split(' ') ) => a0 < b0? -1: a0 > b0? 1: a1 < b1? -1: a1 > b1? 1: 0 ) const customSort2 = sortWith ([ ascend (({name}) => name.split (' ') [0]), ascend (({name}) => name.split (' ') [1] || ''), ]) const customSort3 = sortWith ([ ascend (pipe (prop ('name'), split (' '), prop(0))), ascend (pipe (prop ('name'), split (' '), propOr('', 1))) ]) const array = [{id: '3d4', name: 'A2'}, {id: '9hh', name: 'A3 Beta'}, {id: '7b2', name: 'A1+ Beta'}, {id: '9h5', name: 'A2 Beta'}, {id: '5h4', name: 'A1+ Alpha'}, {id: '1x1', name: 'A1+'}, {id: '1x2', name: 'A2 Alpha'}, {id: '1x3', name: 'A3+'}] console.log (customSort1 (array)) console.log (customSort2 (array)) console.log (customSort3 (array))
.as-console-wrapper {min-height: 100%;important: top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script> <script> const {sortWith, split, ascend, pipe, prop, propOr} = R </script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.