Xpoint
   [напомнить пароль]

Сортировка строк

Метки: [без меток]
[удл]
2007-01-06 02:31:26 [обр] Andrej[досье]

Снова сортировки. Я наверное Вам совсем замучил. :)
Есть несколько файликов с такой конфигурацией:
1156175987|Табл|hel|hel@inbox.lv|1156284692|7|hel|xx|0

Нужно взять все эти файлики, рассортировать по времени и вывести 8 последних. Проблемка заключается в том что я могу вывести только время. А как вывести помимо времени например $temp[1] и $temp[2]?

my @arr=();
foreach my $fname(qw(94322 123454 378211)) {
open (IMEN,"<","$directory/cgi-bin/${fname}.txt") or die "Can't open file $!\n";

for(my $ind=0; <IMEN>; $ind++ ) {
   last if $ind==7; # berem s fajla toljko pervie 7 stro4ek (4tob ne gruzitj zrja vse stroki)
     my @temp=split(/\|/,$_);
     push(@arr,$temp[0]);
}

close(IMEN) or die "Can't close file $!\n";
}

@arr=sort {$b cmp $a} @arr;
print join ("\n<br>"=>@arr);
спустя 5 часов [обр] AB...(10/233)[досье]
Ну и берите первые семь строк целиком а не только время. А потом делайте с ними что Вам угодно.
for(my $ind=0; <IMEN>; $ind++ ) {
  last if $ind==7;
  push(@arr,$_);
}
спустя 8 минут [обр] AB...(10/233)[досье]
На сколько я понял Вам необходимо отсортировать данные из всех трех файлов и потом вывксти 8 строк. В приведенном пример перется только 8 первых записей (точнее время только) с каждого файла и потом сортрируете. Это то, что Вам нужно?
спустя 4 часа 50 минут [обр] Andrej[досье]
AB, да. Нужно отсортировать данные из всех трех файлов по времени и потом вывести 8 строк.
Извените я допустил ошибку при написание скрипта. Сортировать нужно не по $temp[0] а по $temp[4].
спустя 16 часов [обр] AB...(10/233)[досье]

Получается, что нужно 8 строк из трех файлов, а не по 8 строк из каждого файла.
Я не знаю какие новые строки, а какие старые. Возможно лучше всего читать все вайлы целиком. Если предположить, что timestamp всегда уникальный, то проще всего создать элементарный hash, который вы отсортируете по keys, так как Вам необходимо.

my %hash = ();
foreach my $fname (qw(94322 123454 378211)) {
open (IMEN,"<","$directory/cgi-bin/${fname}.txt") or die "Can't open file $!\n";
  for(my $ind=0; <IMEN>; $ind++ ) {
    my @temp=split(/\|/,$_);
    $hash{$temp[4]} = $_;
  }
close(IMEN) or die "Can't close file $!\n";
}

Но если timestamp может совподать, тогда таков метод не подходит. Надо создавать уникальный ключ. Возможно простейшее решение будет изменить создание hash на

my %hash = ();
foreach my $fname (qw(94322 123454 378211)) {
open (IMEN,"<","$directory/cgi-bin/${fname}.txt") or die "Can't open file $!\n";
  for(my $ind=0; <IMEN>; $ind++ ) {
    my @temp=split(/\|/,$_);
    $hash{$_} = $temp[4];
  }
close(IMEN) or die "Can't close file $!\n";
}

В таком варианте меньше всего совпадений - надеюсь. Сортировка тогда уже нужно проводить по value.
А если опять совпадения возможны, тогда задачу надо решать через counter.

my %hash    = ();
my $counter = 0;
foreach my $fname (qw(94322 123454 378211)) {
open (IMEN,"<","$directory/cgi-bin/${fname}.txt") or die "Can't open file $!\n";
  for (my $ind=0; <IMEN>; $ind++ ) {
    my @temp=split(/\|/,$_);
    $counter++;
    for (my $i=0; $i<@temp; $i++) {
      $hash{$counter}{"col".$i} = $temp[$i];
    }
  }
close(IMEN) or die "Can't close file $!\n";
}

Результат будет таковым, что все ваши данные будут пронумерованны и всегда иметь уникальный номер, так как был создан hash of hashes. Значения к примеру вашего четвертого поисково ключа в певой строку будет $hash{1}{col4}. А дальше дело техники отсортировать по подключу и вывести первые восемь значений.

спустя 8 часов [обр] Дмитрий Кучкин(36/236)[досье]
Можно добавлять значения в хэш не присвоением а конкатенацией.
Потом многострочные значения хэша легко разбираются при сортировке.
my %hash = ();
foreach my $fname (qw(94322 123454 378211)) {
  open (IMEN,"<","$directory/cgi-bin/${fname}.txt") or die "Can't open file $!\n";
    while (<IMEN>) {
      my @temp=split(/\|/,$_);
      $hash{$temp[4]} .= $_;
    }
  close(IMEN) or die "Can't close file $!\n";
}

my $counter=8;
foreach (sort {$b <=> $a} keys %hash) {
  foreach (split /\n/,$hash{$_}) {
    last unless $counter--;
    print "$_<br>\n";
  }
  last if $counter<0;
}
спустя 2 часа 44 минуты [обр] AB...(10/233)[досье]
Дмитрий Кучкин[досье], об этом я вообщем уже говорил и указывал как создать данный hash. Как я уже отразил ранее, данный метод ключа несколько опасен, так как вариант соврадения даты больше, чем саоой строки данных.
спустя 6 часов [обр] Дмитрий Кучкин(36/236)[досье]
Опасно присваивать. А у меня строка конкатенируется с той, что уже лежит в хэше. Поэтому при совпадении времени у нескольких строк, все эти строки будут лежать под одним ключом. Никакой опасности.
спустя 8 часов [обр] AB...(10/233)[досье]

Дмитрий Кучкин[досье], вы понимаете о чем вы говорите?
Вот Вам простейшая задачка:

my %hash = ();
$hash{9}  = "a0";
$hash{11} = "a1";
$hash{10} = "b0";
$hash{11} = "b1";

Ответье, что получилочь в $hash{11} при условии, что номер ключа (11) совпал?

спустя 6 часов [обр] Дмитрий Кучкин(36/236)[досье]
Понимаю. В условиях задачи данные несколько другие - это строки, читаемые из файла.
Поэтому корректный тест такой:
my %hash = ();
$hash{9}  = "a0\n";
$hash{11} = "a1\n";
$hash{10} = "b0\n";
$hash{11} = "b1\n";
спустя 5 минут [обр] Дмитрий Кучкин(36/236)[досье]

Блин, запутали меня... :)
У меня же вот так:

my %hash = ();
$hash{9}  .= "a0\n";
$hash{11} .= "a1\n";
$hash{10} .= "b0\n";
$hash{11} .= "b1\n";

print $hash{11};

результат

a1
b1
спустя 22 минуты [обр] Дмитрий Кучкин(36/236)[досье]

AB...[досье]
Вы просто, похоже, не обратили внимания, что в Сортировка строк (352602) в строке 6 не

$hash{$temp[4]} = $_;

а

$hash{$temp[4]} .= $_;

Сам только что не заметил, что в Вашем примере не .=, а = :)

спустя 2 часа 42 минуты [обр] AB...(10/233)[досье]

It is wont work properly. Need additional char as \n

$hash{$temp[4]} .= $_."\n";

Probably better to use second solution where key is a string and timestamp is value. I hope it has really small possibility when full string might be the same.
If avoid any problems but use bigger code better third solution.

спустя 2 часа 21 минуту [обр] Дмитрий Кучкин(36/236)[досье]

Фух...
В текстовом файле каждая строка заканчивается символом \n
При чтении через <> (readline) строка считывается вместе с этим символом. То есть, считанные данные уже имеют в конце символ перевода строки. Прежде чем отправить сюда свой код, я его проверил на данных, считанных из файлов, и убедился, что он работает корректно. Не верите - проверьте.
Единственный случай, когда будет работать неправильно: если в конце последней строки файла отсутствует символ \n, этот файл в списке на обработку не последний, и в каком-нибудь другом файле найдется строка с таким же timestamp. НО такой файл (без \n в конце) по определению НЕ является текстовым, поэтому я таким случаем пренебрег.

Если подставить в мой пример Вашу строку $hash{$temp[4]} .= $_."\n" и проверить на реальных данных, в хэш будут добавляться строки с ДВУМЯ символами \n в конце, и следующий блок с сортировкой и выводом будет отработан неверно, если среди первой восьмерки попадутся значения с одинаковыми timestamp. В выводе окажутся пустые строки (содержащие только <br>). Проверьте.

Если бы это были не основы, я сразу предложил бы практически такое же решение, но работающее корректно всегда, с использованием в качестве значений хэша ссылок на анонимные массивы. Но, боюсь, для автора это будет пока слишком сложно.

my %hash = ();
foreach my $fname (qw(94322 123454 378211)) {
  open (IMEN,"<","$directory/cgi-bin/${fname}.txt") or die "Can't open file $!\n";
    while (<IMEN>) {
      chomp;
      my @temp=split(/\|/,$_);
      push @{$hash{$temp[4]}}, $_;
    }
  close(IMEN) or die "Can't close file $!\n";
}

my $counter=8;
foreach (sort {$b <=> $a} keys %hash) {
  foreach (@{$hash{$_}}) {
    last unless $counter--;
    print "$_<br>\n";
  }
  last if $counter<0;
}
спустя 1 час 3 минуты [обр] Дмитрий Кучкин(36/236)[досье]

Кстати, можно использовать и $hash{$temp[4]} .= $_ . "\n".
Просто тогда в блоке сортировки и вывода надо вместо

  foreach (split /\n/,$hash{$_}) {

написать

  foreach (split /\n+/,$hash{$_}) {

Тогда корректно отработается случай отсутствия \n в конце файла.

Могу согласиться только с тем, что такой метод хранения в хэше не годится для произвольных данных, где разделитель (в данном случае \n) может встретиться где угодно. Но это уже выходит за рамки задачи.

спустя 15 часов [обр] Алексей Севрюков(198/1280)[досье]
М AB...[досье] У нас русскоязычный форум, пишите пожалуйста на русском.
спустя 21 час [обр] AB...(10/233)[досье]
Алексей Севрюков[досье] в основном так и делаю когда есть возможность. Иногда пришу на английском, так как нету русской клавиатуры, да и русский не установлен на рабочем ПК.
Powered by POEM™ Engine Copyright © 2002-2005