Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция sort. 
:(
    Опции темы
dixoNICH
Дата 27.10.2011, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



Как с помощью функции sort можно отсортировать массв строк типа : "sdasdas 10.04.2008 dadsds" по дате? Как-то не понятно совсемушки smile Помогите мыслями, пожалуйста.
PM MAIL   Вверх
vadiml
Дата 27.10.2011, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 27.7.2007

Репутация: 5
Всего: 7



Создать хеш в котором ключами будут вытянутые регэкспом даты из строк, а значениями сами строки, и сделать 
sort keys %этот_хеш
PM MAIL Jabber   Вверх
dixoNICH
Дата 27.10.2011, 23:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



@a = sort { $a cmp $b } keys %datehash;
print Dumper \@a;

$VAR1 = [
          '10.04.2001',
          '10.04.2007',
          '10.04.2009',
          '10.04.2010',
          '10.05.2008',
          '19.02.2008',
          '19.05.2008',
          '20.05.2008'
        ];
не-а
PM MAIL   Вверх
alezzz
Дата 28.10.2011, 08:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


сплю...
**


Профиль
Группа: Участник
Сообщений: 499
Регистрация: 17.8.2009

Репутация: 1
Всего: 14



Когда вытягиваете дату регуляркой, то отдельно вытягивайте день, месяц и год. В хеш сохраните в обратном порядке: ГГГГ.ММ.ДД. 
PM MAIL   Вверх
vadiml
Дата 28.10.2011, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 27.7.2007

Репутация: 5
Всего: 7



Дату для сортировки обычно хранят в ISO формате
YYYY-MM-DD
PM MAIL Jabber   Вверх
dixoNICH
Дата 28.10.2011, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



Спасибо!
Ещё вопрос по дате : Как перевести дату в секунды с помощью DateTime::Format::Epoch;?
Как из секунды в дату я понял, а обратно - неа.
Надо просто перебрать все даты в промежутке, лучше, чем перевод в секунды - ничего не знаю.
PM MAIL   Вверх
ginnie
Дата 28.10.2011, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



dixoNICH, перебрать даты в промежутке можно используя неравенства, перевод в секунды не нужен.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
dixoNICH
Дата 28.10.2011, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



Не намекнёте, как? )
PM MAIL   Вверх
ginnie
Дата 28.10.2011, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



dixoNICH, даны даты 20110123 20110223 20110323, как выбрать из них те, которые попадают в промежуток от 20110101 до 20110301?

Это сообщение отредактировал(а) ginnie - 28.10.2011, 19:32


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
dixoNICH
Дата 28.10.2011, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



д >= 20110101 && д<=20110301

но, всё же, как перебирать то даты? )
PM MAIL   Вверх
ginnie
Дата 29.10.2011, 09:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



dixoNICH, прошу прощения, неправильно понял Ваш вопрос!
Для преобразования даты в unixtime можно использовать Time::Local::timegm(), которая вернет unixtime в UTC (где нет перехода на летнее время):
Код

$time = timegm($sec,$min,$hour,$mday,$mon,$year);

$mon должен быть в интервале [0..11] т.е. на 1 меньше реального, а год на 1900 меньше реального, это сделано для совместимости с функцией gmtime(), которая преобразует unixtime в дату.
Также можно использовать модуль Date::Calc (он XS, поэтому работает довольно быстро), для этой задачи подойдет функция
Код

($year,$month,$day) = Add_Delta_Days($year,$month,$day, $Dd);



Это сообщение отредактировал(а) ginnie - 29.10.2011, 09:06


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
dixoNICH
Дата 31.10.2011, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



не смог с помощью этих функций получить время, которое выдаёт time (
PM MAIL   Вверх
ginnie
Дата 31.10.2011, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



dixoNICH, напишите поконкретнее, что не удалось получить.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
dixoNICH
Дата 31.10.2011, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



уже сделал вручную)
PM MAIL   Вверх
ginnie
Дата 31.10.2011, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 38
Всего: 49



А "вручную" это как?


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Suppir
Дата 31.10.2011, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 20.4.2009

Репутация: нет
Всего: нет



Сортировка с помощью регулярных выражений:


Код

while(<DATA>){
    push(@lines, $_)
};


@sorted = sort {smart_sort()} @lines;

map {print} @sorted;
<>;



sub smart_sort{
    $a =~ / (\d\d).(\d\d).(\d\d\d\d) /;
    $date1 = $3.$2.$1;

    $b =~ / (\d\d).(\d\d).(\d\d\d\d) /;
    $date2 = $3.$2.$1;

    $date2 <=> $date1
}




__DATA__
sdasdas 10.04.2008 dadsds
sdasdas 01.02.2009 dadsds
sdasdas 31.12.2011 dadsds
sdasdas 15.05.2006 dadsds

PM MAIL   Вверх
dixoNICH
Дата 31.10.2011, 15:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 222
Регистрация: 20.3.2011

Репутация: нет
Всего: нет



Код

use Exporter;
@ISA = qw(Exporter); 
@EXPORT_OK = qw(PROCESSOR); 
use DateTime::Format::Epoch;
sub islyear
{
  my $year = shift;

  $year = $year / 100 unless $year % 100;
  return !($year % 4);
}
sub getnday
{
  my $day = substr($_[0], 0, 2);
  my $month = substr($_[0], 3, 2);
  my $year = substr($_[0], 6, 4);
  $day =~ s/^0+//; $month =~ s/^0+//;
  my @days_per_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  $year++ if $year < 0;
  my $days = $day - 1;
  for (my $i = 0; $i < $month - 1; $i++)
  {
    $days += $days_per_month[$i];
  }
  $days++ if islyear($year) && $month > 2;
  $year--;
  $days += $year * 365;
  $days += int($year / 4);
  $days -= int($year / 100);
  $days += int($year / 400);

  return $days;
}
sub getseconds
{
  my $reqdate = $_[0];
  my $secondsinday = 86400;

  # на 1 января 1970 г.
  my $startday = 719162;

  return (getnday($reqdate) - $startday) * $secondsinday;
}
sub arraydate() {
    $d1 = $_[0];
    $d2 = $_[1];
    my $dt = DateTime->new( year => 1970, month => 1, day => 1 );
    my $formatter = DateTime::Format::Epoch->new(
                          epoch          => $dt,
                          unit           => 'seconds',
                          type           => 'int',   
                          skip_leap_seconds => 1,
                          start_at       => 0,
                          local_epoch    => undef,
                      );
    $f = getseconds($d1);
    while($f != getseconds($d2)) {
        $f += 24*3600;
        push @a, $formatter->parse_datetime($f);
    }
    for(@a) {
        /^(\d+)-(\d+)-(\d+)/;
        push @b, "$3.$2.$1";
    }
    return @b;
}

PM MAIL   Вверх
Egik2
Дата 31.10.2011, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 302
Регистрация: 29.7.2008
Где: Агудзера

Репутация: 1
Всего: 11



Код

#!/usr/bin/perl
use Time::Local;
use strict;

my @array = ('10.02.2008', '11.02.2008', '12.02.2008', '01.01.2008');

my @newarray = sort is_time_between @array;

for my $ar (@newarray) {
    print $ar."\n";    
}

sub is_time_between {
   my $start_time = $a;
   my $end_time = $b; #string representing date, format for exampe Nov 17 07:06:42 2009 GMT
   my ($start_day, $start_month, $start_year) = $start_time =~ /(\d+).(\d+).(\d+)/;
   my ($end_day, $end_month, $end_year) = $end_time =~ /(\d+).(\d+).(\d+)/;
   my $start_epoch_time =  timegm(0, 0, 0, $start_day, $start_month, $start_year);
   my $end_epoch_time =  timegm(0, 0, 0, $end_day, $end_month, $end_year);
   if($start_epoch_time > $end_epoch_time) {
      return 1;
   }
   elsif ($end_epoch_time == $start_epoch_time) {
      return 0;
   }
   else {
      return -1;
   }
   
}


Это сообщение отредактировал(а) Egik2 - 31.10.2011, 15:36


--------------------
Три великие добродетели программиста: лень, нетерпение и самомнение (Larry Wall)
a-nav.com
developer-blog.ru
world-poetry.org
PM MAIL WWW ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0961 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.