Sort array that has different types in smalltalk

76 views Asked by At

I tried to run this code to sort an array and got this error

| x sortedX |
x := #('bb' 10 'aa' 2 'cc' 3 5).
sortedX := x asSortedCollection: [:y :z |
    (y class = z class)
        ifTrue: [y < z]
        ifFalse: [y class < z class]
].
Transcript show: sortedX; cr.

Expected to get #(2 3 5 10 ‘aa’ ‘bb’ ‘cc’), but got error: ByteString Class(Object)>>DoesNotUnderstand

2

There are 2 answers

0
Leandro Caniglia On

Here is a version that doesn't depend on classes

x := #('bb' 10 'aa' 2 'cc' 3 5).
sortedX := x asSortedCollection: [:y :z |
    y isInteger = z isInteger
        ifTrue: [y < z]
        ifFalse: [y isInteger]].
0
Christoph Thiede On

I would argue that the following is more idiomatic than the accepted answer:

collection := #('bb' 10 'aa' 2 'cc' 3 5).
sorted := connection sorted:
    [:ea | ea isInteger asBit] ascending
        , #yourself ascending 

Explanation:

  • asSortedCollection[:] creates a self-sorting collection that will update itself after any change. In 95%, you will only need to create a sorted[:] copy of the array (or in some occasions, sort[:] the array inline if you don't mind about side effects).
  • Use SortFunctions (ascending, descending, undefinedFirst, reversed, etc.) instead of two-arg sort blocks for expressing desired order in a more declarative way. For huge (and only huge) collections, check whether it affects performance.
  • asBit converts booleans into numbers (0 and 1ö and thus creates a natural order.