Treehouse: Grow your CSS skills. Land your dream job.

Last updated on:

Sorting Function

Sass does not provide any built-in way to sort a list of values. Thanks to string manipulation functions, we can build a function to sort a list of items following a given order.

If values to be sorted are numbers and numbers only, it ends up being quite easy because Sass can compare them natively.

Sorting numbers

/// Quick sort
/// @author Sam Richards
/// @param {List} $list - list to sort
/// @return {List}
@function quick-sort($list, $order) {
  $less:  ();
  $equal: ();
  $large: ();

  @if length($list) > 1 {
    $seed: nth($list, ceil(length($list) / 2));

    @each $item in $list {
      @if $item == $seed {
        $equal: append($equal, $item);
      } @else if $item < $seed {
        $less: append($less, $item);
      } @else if $seed > $item {
        $large: append($large, $item);
      }
    }

    @return join(join(quick-sort($less, $order), $equal), quick-sort($large, $order));
  }

  @return $list;
}

Sorting numbers and strings

However, if you intend to sort strings as well as numbers, it involves quite a bit of complexity, so let's do it one step at a time.

First, we need a sorting order.

/// Default order used to determine which string comes first
/// @type List
$default-order:
  "!" "#" "$" "%" "&" "'" "(" ")" "*" "+" "," "-" "." "/" "[" "\" "]" "^" "_" "{" "|" "}" "~"
  "0" "1" "2" "3" "4" "5" "6" "7" "8" "9"
  "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" !default;

Then, we need a helper function to determine which value comes first.

/// Compares two string to determine which comes first
/// @access private
/// @param {String} $a - first string
/// @parem {String} $b - second string
/// @param {List} $order - order to deal with
/// @return {Bool}
@function _str-compare($a, $b, $order) {
  @if type-of($a) == "number" and type-of($b) == "number" {
    @return $a < $b;
  }

  $a: to-lower-case($a + unquote(""));
  $b: to-lower-case($b + unquote(""));

  @for $i from 1 through min(str-length($a), str-length($b)) {
    $char-a: str-slice($a, $i, $i);
    $char-b: str-slice($b, $i, $i);

    @if $char-a and $char-b and index($order, $char-a) != index($order, $char-b) {
      @return index($order, $char-a) < index($order, $char-b);
    }
  }

  @return str-length($a) < str-length($b);
}

Last, but not least, we can build our sorting function. The most efficient implementation (that can be ported to Sass) is the quick sort algorithm.

/// Quick sort
/// @author Hugo Giraudel
/// @param {List} $list - list to sort
/// @param {List} $order [$default-order] - order to use for sorting
/// @return {List}
/// @require {function} _str-compare
/// @require $default-order
@function quick-sort($list, $order: $default-order) {
  $less:  ();
  $equal: ();
  $large: ();

  @if length($list) > 1 {
    $seed: nth($list, ceil(length($list) / 2));

    @each $item in $list {
      @if $item == $seed {
        $equal: append($equal, $item, list-separator($list));
      } @else if _str-compare($item, $seed, $order) {
        $less: append($less, $item, list-separator($list));
      } @else if not _str-compare($item, $seed, $order) {
        $large: append($large, $item, list-separator($list));
      }
    }

    @return join(join(quick-sort($less, $order), $equal), quick-sort($large, $order));
  }

  @return $list;
}

If you are interested in the making of such a function, have a look at Implementing Bubble Sort algorithm with Sass at The Sass Way.

Reference URL

Leave a Comment

Posting Code

We highly encourage you to post problematic HTML/CSS/JavaScript over on CodePen and include the link in your post. It's much easier to see, understand, and help with when you do that.

Markdown is supported, so you can write inline code like `<div>this</div>` or multiline blocks of code in in triple backtick fences like this:

```
<script>
  function example() {
    element.innerHTML = "<div>code</div>";
  }
</script>
```