perl6.suОсвоим perl6 к 2015 году!

sort


       Часто приходится массивы сортировать. Ну вот попробуем как это в perl 6.
    
#!/usr/bin/perl6
my @list=<perl6.su rakudo.org perl.org perl6.ru>;
"{@list}".say;
@list=@list.sort;
"{@list}".say;
perl6.su rakudo.org perl.org perl6.ru
perl.org perl6.ru perl6.su rakudo.org

       Что и ожидалось. А если попробовать так?
    
#!/usr/bin/perl6
my @list=<perl6.su rakudo.org perl.org perl6.ru>;
"{@list}".say;
@list=@list.sort.reverse;
"{@list}".say;
perl6.su rakudo.org perl.org perl6.ru
rakudo.org perl6.su perl6.ru perl.org

       Здесь мы сначала отсортировали, а потом перевернули массив. Bene.
       Далее возьмём массивчик побольше, попробуем его посортировать по критериям. Допустим у нас есть сельский роддом, в котором рождаются мальчики и девочки. Мы ведём статистику по месяцам.
    
#!/usr/bin/perl6
my %vir=<jan 10 feb 9 mar 11 apr 10 maj 12 jun 13 jul 15 aug 11 sep 10 oct 7 nov 9 dec 11>;
my %fem=<jan 10 feb 8 mar 10 apr 11 maj 14 jun 10 jul 13 aug 11 sep 9 oct 8 nov 8 dec 8>;
# нам надо отсортировать месяцы по "полезности"
my @lunae=%vir.keys.sort({ %vir{$_}+%fem{$_} }).reverse;
for @lunae {
	say $_,' ',%vir{$_}+%fem{$_}
	}
jul 28
maj 26
jun 23
aug 22
apr 21
mar 21
jan 20
dec 19
sep 19
nov 17
feb 17
oct 15

       Вот. Видно, что июль - самый полезный месяц. Но надо же решить окончательно, что полезнее, март или апрель. Тогда наш вымышленный главврач решил, что надо ввести дополнительный критерий, сравнивать по девочкам. Если девочек родилось больше, то это лучше. Это не шовинизм, а простой расчёт. Потом эти девочки подрастут и тоже станут матерями. Ставим ещё один sort:
    
#!/usr/bin/perl6
my %vir=<jan 10 feb 9 mar 11 apr 10 maj 12 jun 13 jul 15 aug 11 sep 10 oct 7 nov 9 dec 11>;
my %fem=<jan 10 feb 8 mar 10 apr 11 maj 14 jun 10 jul 13 aug 11 sep 9 oct 8 nov 8 dec 8>;
# нам надо отсортировать месяцы по "полезности"
my @lunae=%vir.keys.sort({ %fem{$_} }).sort({ %vir{$_}+%fem{$_} }).reverse;
for @lunae {
	say $_,' ',%vir{$_}+%fem{$_}
	}
jul 28
maj 26
jun 23
aug 22
apr 21
mar 21
jan 20
sep 19
dec 19
nov 17
feb 17
oct 15

       Просто praeclare! Здесь кроется очень приятная особенность sort: он бережно относится с предыдущим порядком. При прочих равных условиях он его сохраняет. Кстати, в нашем примере ноябрь лучше февраля потому, что он в списке позже, а при reverse список развернулся.
       N. B. Чем важнее критерий сравнения, тем ближе к концу цепочки сортов он должен стоять.
# mutatio postrema: 10 Aug 2010


       Способов сортировки три - числовой, алфавитный и смешанный.
    
#!/usr/bin/perl6
my $a=10; my $b=7; my $c='cursor'; my $d='dux';
say $a <=> $b; # $a больше $b
say $a leg $b; # но начинается с меньшего символа
say $a cmp $b; # автоматически используется <=>
# say $c <=> $d; # индиффирентно
say $c leg $d; # $c "меньше", то есть раньше по алфавиту
say $c cmp $d; # автоматически используется leg
Decrease
Increase
Decrease
Increase
Increase

       При сортировке sort по умолчанию используется cmp - сравнение.
       Предположим, у нас проблема. Часть имен записаны с заглавной буквы, часть - нет. Всё равно надо отсортировать имена по алфавиту.
    
#!/usr/bin/perl6
my @list=<Вася петя емеля Джон джордж яша октавиан Николя>;
@list.sort».say;
яша
октавиан
джордж
Джон
петя
емеля
Николя
Вася

       Так нас совсем не устраивает. Предположим, что мы - воспитательница детского сада. Нам позарез необходимо отсортировать подопечных.
    
#!/usr/bin/perl6
my @list=<Вася петя емеля Джон джордж яша октавиан Николя>;
my @sorted=sort { uc($^a) leg uc($^b) }, @list;
@sorted».say;
яша
октавиан
емеля
Джон
петя
Николя
джордж
Вася

       Это - то, что надо. Массив сравнивается попарно, каждая пара заносится в оперативные переменные $^a и $^b, с которыми в фигурных скобках можно вытворять всё, что пожелается душе. Если в нашем примере заменить leg на cmp, то получим тот же результат.
    
#!/usr/bin/perl6
my @list=<Вася петя емеля Джон джордж яша октавиан Николя>;
my @sorted=sort { uc($^a) cmp uc($^b) }, @list;
@sorted».say;
яша
октавиан
емеля
Джон
петя
Николя
джордж
Вася

       Bene. Особенно радует то, что всё хорошо работает и с кириллицей.
# mutatio postrema: 8 Oct 2012


       Другой полезный способ употребления unspace - разбивка строки на несколько.
    
#!/usr/bin/perl6
my @list=<parvo est natura contenta>;
@list.sort\ # это удобно для разбивки длинных строк
	.join(' ... ').say; # и обильных комментариев
contenta ... est ... natura ... parvo

       Заодно попробовали старый добрый join.
       Можно конечно просто разбить длинную строку, без комментариев:
    
#!/usr/bin/perl6
my @list=<parvo est natura contenta>;
@list.sort\
	.reverse\ 
	.join("\n").say; 
parvo
natura
est
contenta

       Ну что же, bene est.
# mutatio postrema: 26 Sep 2011


       Вместо того, чтобы писать @arr=@arr.sort можно воспользоваться укороченной записью @arr.=sort
    
#!/usr/bin/perl6
my @arr=<lego alicui aliquid ab aliquot>;
@arr=@arr.sort;
@arr».say;
'----------'.say;
@arr=<radix studiorum amara>;
@arr.=sort;
@arr».say;
lego
aliquid
ab
aliquot
alicui
----------
studiorum
amara
radix

       Удобно.
# mutatio postrema: 30 Jan 2012

   комментарии, дизайн, <=>, $^a, сортировка массива, cmp, join, leg, reverse, sort      charta situs       nota IX, nota LX, nota LXXXVIII, nota XCIX   

    RSS     stdin@perl6.su    © Alexius Karmanov, 2010-2011