如何在Ramda中组成升序/降序

时间:2019-06-05 15:37:09

标签: javascript sorting ramda.js

我有一个带有排序标题表的React组件。该代码按计划工作:

  //definitions and imports...
  const [sort, setSort] = useState({column: 'rank', direction: 'ascending', isNumber: true});

  const handleSort = (column, isNumber = false) => () => {
    let direction = (sort.column !== column) ? 'ascending' : (sort.direction === 'ascending' ? 'descending' : 'ascending');
    setSort({column, direction, isNumber});
  };

  const getSortedData = (data) => {
    let sorted = R.sortBy(
      R.compose(
        sort.isNumber ? Number.parseFloat : R.toLower,
        R.prop(sort.column)
      ),
      data
    );
    return sort.direction === 'ascending' ? sorted : sorted.reverse();
  }
 //rest of the component...

但是,我确定有一种方法可以使用R.compose来有条件地对ascenddescend进行排序(基于sort.direction属性),从而允许我删除getSortedData的最后一行和reverse数组op。

我尝试了几种方法(例如,将ascendprop一起使用,并使用compose中的条件等等),但这都破坏了代码。

虽然现在效果很好,但是有人可以帮我更Ramda吗?

更新-为子孙后代在此处添加解决方案:

const getSortedData = (data) => {
  return R.sort(
    (sort.direction === 'ascending' ? R.ascend : R.descend)(
      R.compose(
        sort.isNumber ? Number.parseFloat : R.toLower,
        R.prop(sort.column)
      )
    )
  )(data);
}

我学到的东西:

  1. R.sort返回一个函数,而不是数组,因此您需要将data作为参数发送给整个函数。
  2. R.ascend / R.descend也希望该函数用作参数,因此不应单独将其作为R.compose的参数。

2 个答案:

答案 0 :(得分:2)

我想我会做类似的事情,将ascenddescend包裹在构图周围

const makeSorter = (sortConfig) => R.sort (
  (sortConfig.direction === 'descending' ? R.descend : R.ascend) ( R.compose (
    sortConfig.isNumber ? Number.parseFloat : R.toLower,
    R.prop (sortConfig.column)
  ))
)

const people = [
  {name: 'fred', age: 25},
  {name: 'barney', age: 28},
  {name: 'wilma', age: 29},
  {name: 'betty', age: 22}
]

const byName = {direction: 'descending', column: 'name', isNumber: false}

const getSortedData = makeSorter(byName)

console .log (
  getSortedData (people)
)

const byAge = {direction: 'ascending', column: 'age', isNumber: true}

console .log (
  makeSorter (byAge) (people)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

我个人更喜欢用破坏性的方式来编写它,例如:

const makeSorter = ({direction, isNumber, column}) => R.sort (
  (direction === 'descending' ? R.descend : R.ascend) ( R.compose (
    isNumber ? Number.parseFloat : R.toLower,
    R.prop (column)
  ))
)

但这并没有改变任何基本面。

答案 1 :(得分:0)

您可以将ascenddescendconverge一起使用:

  1. 第一个分支可以算出是升序还是降序
  2. 第二个分支确定排序应在哪个字段(以及哪个转换)上进行

const arr = [{a: 10, b: 'ZZZ'}, {a: 5, b: 'ccc'}, {a: 11, b: 'aaa'}];

const makeSort = converge(call, [
  ({dir}) => dir === 'ascending' ? ascend : descend,
  ({isNumber, key}) => isNumber ? compose(parseFloat, prop(key)) : compose(toLower, prop(key))]);

const ascSortB = makeSort({dir: 'ascending', isNumber: false, key: 'b'});
const descSortA = makeSort({dir: 'descending', isNumber: true, key: 'a'});

console.log(sort(ascSortB, arr));
console.log(sort(descSortA, arr));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
<script>const {sort, ascend, descend, prop, converge, call, compose, toLower} = R;</script>

您可能还会发现this post有用