Хорошо, у вас есть несколько мелких проблем. Однако зачастую легче отладить одну большую проблему, чем несколько мелких.
Использование 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}]
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>