I need to sort a table that has columns of varying data types. The problem with sorting the strings is that they are case sensitive. The original code is
const Details = sortWith(
sortDir === 'ASC'
? ascend((row) => row.data[col])
: descend((row) => row.data[col])
)
and I updated it to the following which works
const Details = sortWith(
sortDir === 'ASC'
? ascend((row) => typeof row.data[col] === 'string' ? row.data[col].toLowerCase() : row.data[col])
: descend((row) => typeof row.data[col] === 'string' ? row.data[col].toLowerCase() : row.data[col])
)
Is there a better way to do this?
Welcome to Stack Overflow. Please, in the future, try to post a Minimal Reproducible Example with your question.
I'm not sure whether this will help, but here is a configuration-based sorting function generator, built on Ramda's sorting capabilities:
const mySorter = (config) =>
sortWith (config .map (
({col, sortDir = 'ASC'}) => (sortDir == 'ASC' ? ascend : descend)
(pipe (path (['data', col]), when (is (String), toLower)))
))
const data = [{data: {first: 'Fred', last: 'Flintstone', age: 31}}, {data: {first: 'Wilma', last: 'Flintstone', age: 29}}, {data: {first: 'pebbles', last: 'flintstone', age: 1}}, {data: {first: 'Barney', last: 'Rubble', age: 29}}, {data: {first: 'bambam', last: 'Rubble', age: 1.5}}, {data: {first: 'Betty', last: 'Rubble', age: 33}}]
console .log (
mySorter ([{col: 'age'}, {col: 'last', sortDir: 'DESC'}]) (data)
)
console .log (mySorter ([{col: 'first'}]) (data))
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js"></script>
<script>const {sortWith, ascend, descend, pipe, path, when, is, toLower} = R</script>
The part about lowercasing only the strings is when (is (String), toLower), which seems eminently readable.
If you want to avoid repeating yourself on the sorting you can isolate the typecheck function:
const stringCheck = (row) => typeof row.data[col] === 'string' ? row.data[col].toLowerCase() : row.data[col]
and then:
const Details = sortWith(
sortDir === 'ASC'
? ascend(stringCheck)
: descend(stringCheck)
)
You can use the optional function call, it will be executed only if that method is defined for the type:
row.data[col].toLowerCase?.() ?? row.data[col]
The optional function call will return undefined whether the method is not defined, for this reason we need ?? row.data[col] in order to retrieve the previous value.