I am trying to make a new sorting method in smalltalk. Anyone know how to change this sorting java code to squeak?
public static void SelectionSort ( int [ ] num )
{
int i, j, first, temp;
for ( i = num.length - 1; i > 0; i - - )
{
first = 0; //initialize to subscript of first element
for(j = 1; j <= i; j ++) //locate smallest element between positions 1 and i.
{
if( num[j] < num[first] )
first = j;
}
temp = num[first]; //swap smallest found with element in position i.
num[first] = num[ i ];
num[i] = temp;
}
}
Short answer:
You don't have to.
To sort an array, just send it the message #asSortedCollection
. For instance, inspect this in a workspace:
#(7 2 8 5) asSortedCollection
Long answer:
Since I assume you want to see how you would implement the equivalent of your Java code in Smalltalk if you really had to, here's a relatively "literal translation" you can test in a workspace (tested in Pharo, should work in Squeak as well):
| someNumbers |
someNumbers := #(7 2 8 5) copy. "See comments below for an explanation."
someNumbers size to: 1 by: -1 do: [:eachOuterIndex |
| indexOfSmallest swapValue |
indexOfSmallest := 1.
1 to: eachOuterIndex do: [:eachInnerIndex |
(someNumbers at: eachInnerIndex) < (someNumbers at: indexOfSmallest)
ifTrue: [ indexOfSmallest := eachInnerIndex ]
].
swapValue := someNumbers at: indexOfSmallest.
someNumbers at: indexOfSmallest put: (someNumbers at: eachOuterIndex).
someNumbers at: eachOuterIndex put: swapValue.
].
^someNumbers
Clearly, there are a few changes from your version, such as using explicit naming, which is one of Smalltalk's hallmark conventions (in particular, indexOfSmallest
should be clearer than first
, which is misleading since it's not necessarily the first index), and decreasing the scope of the variables you called first
and temp
). See @Leandro's answer for a version that uses your own variable names if you have trouble with the "translation".
If the code were to live in a method, I would probably put it in the SequenceableCollection
hierarchy (or maybe you'd want to add yours as a subclass in there if you want to override other behaviour), and the start of it could look something like this:
copySortedDescending
"Answer a copy of the receiver, sorted in descending order."
| copy |
copy := self copy.
copy size to: 1 by: -1 do: [:eachOuterIndex |
"... and so on..."
].
^copy
Again, note that I'm deliberately changing the name, because I don't think selectionSort
is a descriptive name of what the method does, and I wouldn't use a collection as an argument to a method living somewhere else - the knowledge of how to do the sorting belongs on the collection itself.
I'm sure you could come up with a better roll-your-own-answer very easily, though. For instance, you could try sending a SequenceableCollection
instance the message sort:
and pass a sort block as an argument, in which you could specify how you want your elements to be sorted.
Here is a line by line translation. Row numbers are not part of the code.
1. selectionSort: num
2. | first temp |
3. num size to: 1 by: -1 do: [:i |
4. first := 1. "initialize to subscript of first element"
5. 1 to: i do: [:j |
6. "locate smallest element between positions 1 and i"
7. (num at: j) < (num at: first) ifTrue: [first := j]].
8. temp := num at: first. "swap smallest with element in position i"
9. num at: first put: (num at: i).
10. num at: i put: temp]
Remarks:
i
and j
declared inside blocks (lines 3 and 5). In Smalltalk, indexed collections are 1 based.num.length()
-> num size
. Decreasing for
loop translates into to:by:do:
message.=
becomes :=
and 0
becomes 1
(see line remark 2 above.)for
loop translates into to:do:
message.[j]
translates into the at: j
message. if
translates into an ifTrue:
message.temp
could have been declared in the first block: do: [:i | | temp |...
.num[j] = temp
also becomes a message sending at:put:
.Idem 9. Note also that you could have used the cascade syntax for lines 9 and 10:
num
at: first put: (num at: i);
at: i put: temp
No need to answer num
because it's been modified by the method. See, however, the interesting discussion originated in Amos' answer: Why shouldn't I store into literal arrays in Smalltalk?.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With