Sorting records

Hello friends! I am displaying some tabular data (typed as a record) from my back-end and I have implemented sorting on all columns, but I couldn’t find a way to do it parametrically; each record field has its own sorter:

let sortMyField = (dir: sortDirection, n1: myType, n2: myType) =>
  switch dir {
  | Up =>
    switch n2.myField > n1.myField {
    | true => 1
    | false => -1
    }
  | Down =>
    switch n2.myField <= n1.myField {
    | true => 1
    | false => -1
    }
  }

It works (simplified) like this: user clicks button on top of column, the onClick handler receives the field name, calls a sort function that switches on the field name, calling in turn Js.Array2.sortInPlaceWith with the field-specific sorter function, which must return an int. Any non-int field has a sorter as shown above, otherwise it’s a little simpler. The data then is replaced with the new sort and the user sees it. In the previous JS version of this project I had:

export default function playerSort(crit, dir) {
  return function innerSort(p1, p2) {
    if (p1[crit] > p2[crit]) {
      return dir;
    } else if (p1[crit] == p2[crit]) {
      if (p1.name.toLowerCase() > p2.name.toLowerCase()) {
        return 1;
      } else {
        return -1;
      }
    } else {
      return -1 * dir;
    }
  }
}

where I could parameterize the object property, but I tried both records and ReScript objects and couldn’t find a way to do this. I just wanted to see if this code could be cut down some. I have 6 columns so far, so 6 sorters that differ only in the field name being sorted. Thank you.

Perhaps bundle all the sorting logic in a single function and switch by field name? E.g.,

type dir = Up | Down
type myType = {myField: string}

let sort = (fieldName, dir, myType1, myType2) => {
  let res = switch fieldName {
    | "myField" => compare(myType1.myField, myType2.myField)
    | _ => invalid_arg(fieldName)
  }
  
  switch dir {
  | Up => res
  | Down => -1 * res
  }
}

Then you should be able to get a sorting function for each possible sorting event by calling sort(fieldName, dir).

1 Like

Interesting, I will play around with this. Thank you!

1 Like