如何在smalltalk中进行排序方法

pro*_*irl 4 sorting methods smalltalk squeak

我试图在smalltalk中创建一个新的排序方法.有谁知道如何改变这个排序java代码吱吱声?

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; 
      }           
}
Run Code Online (Sandbox Code Playgroud)

Amo*_*ter 7

简短回答:

你不必.

要对数组进行排序,只需向其发送消息即可#asSortedCollection.例如,在工作区中检查它:

#(7 2 8 5) asSortedCollection
Run Code Online (Sandbox Code Playgroud)

答案很长:

因为我想,你希望看你怎么实现的Smalltalk的Java代码的等价的,如果你真的有到,这里是一个相对"直译",您可以在工作区试验(菲罗测试,应在佳乐以及工作) :

| 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
Run Code Online (Sandbox Code Playgroud)

很明显,你的版本有一些变化,例如使用明确的命名,这是Smalltalk的标志性约定之一(特别是,indexOfSmallest应该更清楚first,因为它不一定是第一个索引,这是误导性的),并且缩小范围你调用的变量firsttemp).如果您在使用"翻译"时遇到问题,请参阅@ Leandro对使用您自己的变量名称的版本的回答.

如果代码存在于一个方法中,我可能会将它放在SequenceableCollection层次结构中(或者如果你想覆盖其他行为,你可能希望将你的子类添加为子类),并且它的开头可能看起来像什么像这样:

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
Run Code Online (Sandbox Code Playgroud)

再次注意,我故意更改名称,因为我不认为selectionSort该方法的描述性名称是什么,我不会将集合用作生活在其他地方的方法的参数 - 如何知道如何排序属于集合本身.

不过,我确信你可以很容易地找到一个更好的自己动手的答案.例如,您可以尝试发送SequenceableCollection消息实例并将sort:排序块作为参数传递,您可以在其中指定元素的排序方式.

  • 对,那是正确的.但是假设您在方法中编写此代码.你期望每次调用它时,第一行是相同的,但是在第一次调用之后这不是真的.这有点复杂,所以我创建了一个社区wiki条目:/sf/ask/2097504181/#29964346 (2认同)

Lea*_*lia 6

这是一行一行的翻译.行号不是代码的一部分.

 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]
Run Code Online (Sandbox Code Playgroud)

备注:

  1. 没有参数类型声明.没有答案类型.
  2. 阻止临时ij内部块(第3和第5行).在Smalltalk中,索引集合是基于1的.
  3. num.length()- > num size.减少for循环转换为to:by:do:消息.
  4. 分配=变为:=0变为1(参见上面的第2行).
  5. 增加for循环转换为to:do:消息.
  6. 注释括在双引号之间.
  7. [j]转化为at: j信息.if翻译成一条ifTrue:消息.
  8. temp可以在第一个块中声明:do: [:i | | temp |....
  9. num[j] = temp也成为一个消息发送at:put:.
  10. 同样9.还要注意您可以使用第9行和第10行的级联语法:

    num
        at: first put: (num at: i);
        at: i put: temp
    
    Run Code Online (Sandbox Code Playgroud)
  11. 无需回答,num因为它已被方法修改.然而,请参阅Amos回答的有趣讨论:为什么我不应该存储在Smalltalk的文字数组中?.