как да направя метод за сортиране в smalltalk

Опитвам се да направя нов метод за сортиране в smalltalk. Някой знае ли как да промени този сортиращ java код на 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; 
      }           
}

person programmingGirl    schedule 30.04.2015    source източник


Отговори (2)


Ето превод ред по ред. Номерата на редовете не са част от кода.

 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]

Забележки:

  1. Няма декларация за тип аргумент. Няма тип отговор.
  2. Временни блокове i и j, декларирани вътре в блокове (редове 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
    
  11. Няма нужда да отговаряте на num, защото е модифициран от метода. Вижте обаче, интересната дискусия произлиза от отговора на Амос: Защо не трябва да съхранявам в буквални масиви в Smalltalk?.

person Leandro Caniglia    schedule 30.04.2015
comment
Благодаря ти! това беше изключително ясно и полезно! промених малко начина, но това обясни кода стъпка по стъпка. - person programmingGirl; 01.05.2015

Кратък отговор:

Не е нужно.

За да сортирате масив, просто му изпратете съобщението #asSortedCollection. Например, проверете това в работно пространство:

#(7 2 8 5) asSortedCollection

Дълъг отговор:

Тъй като предполагам, че искате да видите как бихте приложили еквивалента на вашия Java код в Smalltalk, ако наистина трябва, ето сравнително „буквален превод“, който можете да тествате в работно пространство (тествано във Pharo, трябва да работи и в Squeak):

| 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

Ясно е, че има няколко промени от вашата версия, като например използването на изрично именуване, което е една от отличителните конвенции на Smalltalk (по-специално, indexOfSmallest трябва да е по-ясно от first, което е подвеждащо, тъй като не е непременно първият индекс), и намаляване на обхват на променливите, които сте извикали first и temp). Вижте отговора на @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

Отново имайте предвид, че умишлено променям името, защото не мисля, че selectionSort е описателно име за това какво прави методът и не бих използвал колекция като аргумент за метод, живеещ някъде другаде - знанието на как да направите сортирането принадлежи на самата колекция.

Сигурен съм обаче, че много лесно бихте могли да измислите по-добър собствен отговор. Например, можете да опитате да изпратите на SequenceableCollection екземпляр съобщението sort: и да подадете блок за сортиране като аргумент, в който можете да посочите как искате вашите елементи да бъдат сортирани.

person Amos M. Carpenter    schedule 30.04.2015
comment
Вашият код е най-вече правилен, но не трябва да съхранявате в литерал масив (#(...)). Вероятно променете първия ред на someNumbers := #(7 2 8 5) copy. - person Tobias; 30.04.2015
comment
@Tobias: Както казах, има за цел да бъде буквален превод на кода на OP. И работи както е във Pharo... защо не промените стойностите в него? Аз не итерирам над масива, аз итерирам над индекси. - person Amos M. Carpenter; 30.04.2015
comment
Да това е вярно. Но да предположим, че пишете този код в метод. бихте очаквали, че всеки път, когато го извикате, първият ред е един и същ, но това не е вярно след първото извикване. Това е малко сложно, затова направих вписване в уики общността: stackoverflow.com/questions/29964345/ - person Tobias; 30.04.2015
comment
@Tobias: Оценявам усилията, които положихте, за да изразите мнението си, което е доста труден случай - гласувах в подкрепа както на въпроса, така и на отговора ви там. Ако този код трябваше да живее в метод, вместо просто да бъде пример за работно пространство, очевидно литералният масив нямаше да бъде използван на първо място - масивът щеше да бъде аргументът, а методът би най- вероятно отговаря на сортирано копие на приемника. Радваме се да актуализираме отговора, за да включим copy все пак, благодаря, че посочихте това. - person Amos M. Carpenter; 30.04.2015