Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Perl (http://www.flasher.ru/forum/forumdisplay.php?f=21)
-   -   как отсортировать? :( (http://www.flasher.ru/forum/showthread.php?t=54140)

WD` 29.01.2004 00:24

как отсортировать? :(
 
.. есть, например, 3 массива - парвый - имя, второй - фамилия, 3 - телфон. Можно ли без дополнительных ивращений отсортировать по 2му или 3му массиву? или прийдется объединять в один, сортировать, а потом разделять снова?

SPV 29.01.2004 20:00

Я бы ввел хэш из сортируемого массива, где ключи - элементы массива, а значения - их индексы... Потом сортируем массив и из хэша получаем отсортированные индексы, зная которые автоматом получаем отсортированные все остальные массивы... во навернул :) Лучше на примере:
Код:

@arr1 = ('a', 'b', 'c', 'c');
@arr2 = ('b', 'c', 'a', 'c');
@arr3 = ('c', 'a', 'b', 'c');
@sorted = &sortIndexes(\@arr3);
foreach my $i(@sorted) {
  print $arr1[$i]." - ".$arr2[$i]." - ".$arr3[$i]."\n";
}

sub sortIndexes {
  my $arr = shift;
  my %hash = ();
  foreach my $i(0..$#{$arr}) {
    @{$hash{$arr->[$i]}} = () if (!defined $hash{$arr->[$i]});
    push @{$hash{$arr->[$i]}}, $i;
  }
  my @result = ();
  foreach my $sorted(sort @{$arr}) {
    push @result, @{$hash{$sorted}};
    @{$hash{$sorted}} = ();
  }
  return @result;
}


WD` 30.01.2004 13:33

10x :)
можно еще такую наглость как пару вопросов после всего написанного? :P
$#{$arr} - получаем размер массива? а что за {} ? :)
@{hash{$i} - @{ ?
@{$arr} - ? :)

ЗЫ: есть книжка маленькая по хэшам, но там почти ничего нет из тобой написанного.. это вообще урезанный перевод Perl Cookbook.
Есть Perl Cookbook на русском в электронном виде? существует вообще? а то на инглише туго идёт :(

а так реализация Твоя просто супер :)) то что надо :)
еще раз большое спасибо :)

SPV 30.01.2004 14:05

1. Мы передаем в функцию не сам массив, а ссылку на него \@arr3 (со слэшем вначале) - это чтобы память не засорять и мало-ли потом нужно будет ещё какие-нить параметры добавить... Соответственно если внутри функции в переменной $arr ссылка на массив, а нам нужен он сам, то достаем его так: {$arr}. Элемент массива можно из ссылки выташить так: $arr->[$i].
2. Так как в сортируемом массиве могут оказаться одинаковые элементы, то значением в хэше для этого элемента должен быть не один индекс, а несколько, иначе мы потеряем все одинаковые элементы. Тут можно было либо просто в строке эти индексы перечислить, а потом разбить эту строку:
Код:

  foreach my $i(0..$#{$arr}) {
    $hash{$arr->[$i]} .= $i.",";
  }
  my @result = ();
  foreach my $sorted(sort @{$arr}) {
    push @result, split (",", $hash{$sorted});
    $hash{$sorted} = "";
  }

Либо как сделал я - Элементами кэша являются массивы, а не строки, что позволяет не делать потом split. Т.е. мы сначала объявляем элемент хэша как массив: @{$hash{$arr->[$i]}} = () а потом добавляем в этот массив индексы.

Да, только сейчас заметил, что при генерации результата лучше сделать так:
Код:

  my @result = ();
  foreach my $sorted(sort keys %hash) {
    push @result, @{$hash{$sorted}};
  }

Тогда не будем повторно пробегать по одинаковым элементам исходного массива :)

WD` 31.01.2004 00:18

я перед тем как написать предыд. пост разбирался что ты написал :)
где знал, где нет - методом тыка и исключений:)
понял что передаёш ссылку на массив.. предположил что {$arr} это получение массива по ссылке, попробовал его print'ом взять но он не дался :)
Как функционирует и что как делается понял.. сидел разбирал каждую строку.. :) понял!:)
Проблема была в самом синтаксисе.. я его не очень знаю.. а тем более все его варианты :)
Единственной загадкой для меня осталась конструкция
@{$hash{'a'}}
это что за @?
просто ты написал
@{$hash{$arr->[$i]}} = () if (!defined $hash{$arr->[$i]});
но левая и правая конструкции разные.. в чём?

я б написал так (ессно после твоей подсказки:) )
Код:

#!usr/bin/perl
@arr1 = ('aa', 'b', 'c', 'c');
@arr2 = ('bb', 'c', 'a', 'c');
@arr3 = ('cc', 'a', 'b', 'c');
@sorted = &sortIndexes(\@arr3);
foreach my $i(@sorted)
 { print $arr1[$i]." - ".$arr2[$i]." - ".$arr3[$i]."\n"; }
sub sortIndexes {
  my $arr = shift;
  my %hash = ();
  foreach my $i(0..$#{$arr}) { $hash{$arr->[$i]}=$i; }
  my @result = ();
  foreach my $sorted(sort keys %hash)
  {
    push @result, $hash{$sorted};
    delete $hash{$sorted};
  }
  return @result;
}

можно еще 2 слова о shift'е? просто я знал только @_[] а shift.. :)
ЗЫ: но идея класс :) почему мне такая не пришла? :P
ЗЗЫ: Может подскажешь хоть алгоритм как проще реализовать слегка измененную эту задачу.. слегка это: теперь массивы содержат не списки имен/фамилий/.. , а записи, типа @arr1=["Иван","Иванович","Иванов"];@arr2=[]..
:)

metton 10.02.2004 00:52

Что-то я не понял что нужно в изменённой задаче сортировать...
Ещё не понятно, что ты хотел сказать вот этой срокой:
@arr1=["Иван","Иванович","Иванов"];
что первый элемент массива ссылка на массив?
или же что это массив (тогда нужны круглые вместо квадратных скобок)?

WD` 14.02.2004 19:21

да, скоббки круглые..
в 1 случае - массив имен, массив фамилии,
а во 2 - массив это запись имя-фамилия-..

metton 14.02.2004 19:36

2WD`
Цитата:

а во 2 - массив это запись имя-фамилия-..
И что нам, пгастите тогда нужно сортировать? :D


Часовой пояс GMT +4, время: 23:23.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.