Sorting By Functions in Nim

Sometimes we’ll want to sort a collection by something other than its natural order. For example, suppose we wanted to sort strings by their length instead of alphabetically. Here’s an example of custom sorts in Nim.

import algorithm, sequtils

proc main() =
  var fruits = @["peach", "banana", "kiwi"]

  # We implement a comparison function for string lengths.
  proc lenCmp(a, b: string): int =
    cmp(a.len, b.len)

  # Now we can call sort with this custom comparison function
  # to sort `fruits` by name length.
  fruits.sort(lenCmp)
  echo fruits

  # We can use the same technique to sort a sequence of
  # values that aren't built-in types.
  type
    Person = object
      name: string
      age: int

  var people = @[
    Person(name: "Jax", age: 37),
    Person(name: "TJ", age: 25),
    Person(name: "Alex", age: 72)
  ]

  # Sort `people` by age using a custom comparison function.
  people.sort(proc(a, b: Person): int = cmp(a.age, b.age))
  echo people

main()

In this Nim code:

  1. We import the algorithm module for sorting and sequtils for sequence operations.

  2. We define a lenCmp procedure that compares strings based on their length.

  3. We use the sort procedure from the algorithm module, passing our custom comparison function to sort the fruits sequence by string length.

  4. For sorting custom types, we define a Person object type with name and age fields.

  5. We create a sequence of Person objects and sort it using an anonymous procedure that compares the age field.

  6. The sort procedure in Nim modifies the sequence in-place, similar to the slices.SortFunc in the original example.

Note: Nim’s standard library provides powerful sorting capabilities out of the box, making custom sorting relatively straightforward. The cmp function is built into Nim and doesn’t require an additional import.

To run the program, save it as sorting_by_functions.nim and use the Nim compiler:

$ nim c -r sorting_by_functions.nim
@["kiwi", "peach", "banana"]
@[(name: "TJ", age: 25), (name: "Jax", age: 37), (name: "Alex", age: 72)]

This example demonstrates how to implement custom sorting in Nim, which can be applied to both built-in types and user-defined types.