DEV Community

Arthur Christoph
Arthur Christoph

Posted on • Edited on

Polyglot Series in Javascript, Dart, Ruby, Python,Go: Sorting List

Preface

This is the first post of the series that will dive into my journey in exploring these languages, some of which I have years of experience (Javascript, Ruby) and those are newer to me (Dart, Go).
As there are many aspects of programming language that we can explore and compare, my exploration will emphasize on the cookbook-style approach - how to solve common problems like sorting, filtering, etc, while comparing the unique features of the language.
I hope these posts will help new learners to get started with the languages and experienced learners alike to reinforce/refresh your understanding.
Last but not least, your feedbacks are very welcome to help me revise these posts with more contents, alternate solutions or even better ones.

Sorting List / Array

Scripts are located under the following path: collection/list/sort
The script has been structured with the following content:

  • Sort methods can either returns a new array or modify existing one
  • Sort methods with a single comparator and multiple comparators
  • Sort list of string in numeric order and vice versa
  • Sort a numeric list

Javascript

  • the sort method accepts the comparator function, if not specified, the elements are converted to string and ordered in UTF-16 code units order.
  • if supplied, the comparator function fn(a,b) is expected to return:
    • a negative number for a order less than b
    • a positive number for a order greater than b
    • a zero for equal order
    • typically, -1, 1, and 0 is used to represent these values
  • In Javascript, 0 value is evaluated as false when treated as boolean. This enable a nice hack when sorting the list with multiple comparator using OR operator. So, as in the example below, if the length of a and b is equal, the returned 0 value is evaluated as false, which then execute continue to invoke the second comparator byLowerCase. It makes the code looks so succinct.
c.sort((a, b) => byLength(a, b) || byLowerCase(a, b));

Another nice hack is we can take advantage of the comparator function convention to write a succinct line when sorting a numeric array by calculating the value difference of a and b. Javascript unfortunately needs this, since sort() without argument will sort by string value.

f.sort((a, b) => a - b);

Dart

  • Instead of using low-level comparator condition, Dart has a helper function compareTo that behaves just like the Javascript comparator
byLength(a, b) {
  return a.length.compareTo(b.length);
}
  • When using multiple comparators, unlike Javascript, we cannot use the OR operator hack - Dart expects a literal boolean value, so the approach is to have the comparator functions in an array that will execute the next comparator if the current one is zero (equal order)
var sortFunctions = [byLength, byLowerCase];
  c.sort((a, b) {
    var i = 0;
    var r = 0;
    while (r == 0 && i < sortFunctions.length) {
      r = sortFunctions[i++](a, b);
    }
    return r;
  });

Ruby

  • The idiomatic Ruby gives us the 'spaceship' <=> comparator, equivalent to comparator we have seen in JS and Dart. It does look like the body of a flying saucer from the sideview :)
def by_length(a,b)
  return a.length <=> b.length
end
  • Unlike Javascript and Dart, both Ruby and Python have specific sort method to either modify the current array or create a new copy of sorted array. In Ruby API, the use of exclamation point at the end of method is to indicate that the method is mutating the current object instead of making a new one. I love this idiomatic.
a.sort! {|a,b| by_lower_case(a,b) }
  • sort_by can be used to shorten the need of passing a and b. The use of ampersand colon is another idiom in Ruby to make even morse terse syntax
a.sort! {|a,b|  a.downcase <=> b.downcase}
a.sort_by! { |e| e.downcase }
a.sort_by!(&:downcase)
  • Ruby converts 0 to false in OR operation, so the same nice hack of Javascript can be done as well. Nice :)
c = a.sort {|a,b|  by_length(a,b) || by_lower_case(a,b) }

Python

  • Python has sorted function to return a new sorted list and the .sort to modify the current list
  • Instead of defining a comparator function(a,b), Python's sort and sorted have key argument which can specify either: a compare function or a tuple consisting the comparator functions. The shortest of all we have seen so far.
b = sorted(a, key=by_lower_case)
c = sorted(a, key=(len(item), item.lower()))

Go

  • Go has a less straightforward way of copying a list using the make and copy combo, makes it more verbose to sort that produces a new sorted array
  • Two ways to sort:
    1. use comparator type which implements three functions: Len, Swap and Less. Multiple comparators one is not easy - need to implement a new method that consist for the logic to compare in sequential order of the comparators.
    2. use Slice function, which only needs the Less function
type byLength []string

func (s byLength) Len() int {
    return len(s)
}

func (s byLength) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}

func (s byLength) Less(i, j int) bool {
    return len(s[i]) < len(s[j])
}
a := []string{"Art", "b", "ART"}
c := make([]string, len(a))
copy(c, a)
sort.Sort(byLength(a))

// Slice method
f := []int{3, 1, 2}
sort.Slice(f, func(i, j int) bool {
 return f[i] < f[j]
})
  • Unlike other languages, the string to integer conversion has the golang style of returning multiple values, two values: the value and the error if any
ei, _ := strconv.Atoi(e[i])

Summary

We have seen many different features of these languages, just by exploring sorting a list problem. In the sequential posts of the series, I will try to not repeat the same language feature discussion, to keep the posts simpler and more to the point, as we are getting more skilled after this first journey. Onward Polyglots!

Top comments (0)