Понадобилась тут функция сортировки массива. Что-то типа php-шного natsort, только ширше. Массив может включать десятичные дроби, обычные дроби, строки, диапазоны, обозначения в дюймах и списки, состоящие из всего перечисленного. Ясен пень, одновременно.
Сохраню себе тут, мало ли где еще может пригодится.
Код:my @out = sort natsort @inp;Код:sub natsort { my $calc_index = sub { my ($val) = @_; $val =~ s/^\s+|\s+$//g; my ( $index, $isstr ) = ( $val, 1 ); $val =~ s/\s*("|\.|'{1,2})$//g; if ( $val =~ m/^[+-]?\s*(\d+\s*\.\s*|\.\s*)?\d+$/ ) { $isstr = 0; $index = $val; $index =~ s/\s+//g; $index += 0; } elsif ( $val =~ m/^([+-]?)\s*(\d+)\s*\/\s*(\d+)$/ ) { if ( $3 > 0 ) { $isstr = 0; $index = 0 + ( $1 . $2 / $3 ); } } elsif ( $val =~ m/^([+-]?)\s*(\d+)\s+(\d+)\s*\/\s*(\d+)$/ ) { if ( $4 > 0 ) { $isstr = 0; $index = 0 + ( $1 . ( $2 + $3 / $4 ) ); } } return ( $index, $isstr ); }; my $prepare = sub { my ($val) = @_; if ( index( $val, ',' ) > -1 ) { my @arr; my @sub = split( /,/, $val ); foreach my $i (@sub) { my ( $index, $isstr ) = $calc_index->($i); push @arr, { i => $isstr, v => $index }; } return @arr; } if ( $val =~ m/^(.*[\d\s\."'])\-([\d\s\.].*)$/ ) { my ( $index1, $isstr1 ) = $calc_index->($1); my ( $index2, $isstr2 ) = $calc_index->($2); if ( $isstr1 == 0 && $isstr2 == 0 ) { return ( { i => $isstr1, v => $index1 } ); } } if ( $val =~ m/^([^и]*)и(.*)$/i ) { my ( $index1, $isstr1 ) = $calc_index->($1); my ( $index2, $isstr2 ) = $calc_index->($2); if ( $isstr1 == 0 && $isstr2 == 0 ) { return ( { i => $isstr1, v => $index1 }, { i => $isstr2, v => $index2 }, ); } } my ( $index, $isstr ) = $calc_index->($val); return ( { i => $isstr, v => $index } ); }; my @arr_a = ( $prepare->($a) ); my @arr_b = ( $prepare->($b) ); for ( my $i = 0; $i <= $#arr_a; $i++ ) { if ( $arr_a[$i]->{i} != $arr_b[$i]->{i} ) { return $arr_a[$i]->{i} <=> $arr_b[$i]->{i}; } my $cmp = 0; if ( $arr_a[$i]->{i} == 1 ) { $cmp = $arr_a[$i]->{v} cmp $arr_b[$i]->{v}; } else { $cmp = $arr_a[$i]->{v} <=> $arr_b[$i]->{v}; } if ( $cmp != 0 ) { return $cmp; } } return ( $#arr_a > $#arr_b ) ? 1 : -1; }
-
Скрыть объявление
Друзья, в это тяжёлое и непонятное для всех нас время мы просим вас воздержаться от любых упоминаний политики на форуме, - этим ситуации не поможешь, а только возникнут ненужные ссоры и обиды. Это касается также шуток и юмора на тему конфликта. Пусть войны будут только виртуальными, а политики решают разногласия дипломатическим путём. С уважением, администрация Old-Games.RU.
-
Скрыть объявлениеЕсли Вы видите это сообщение, значит, вы ещё не зарегистрировались на нашем форуме.
Зарегистрируйтесь, если вы хотите принять участие в обсуждениях. Перед регистрацией примите к сведению:
- Не регистрируйтесь с никами типа asdfdadhgd, 354621 и тому подобными, не несущими смысловой нагрузки (ник должен быть читаемым!): такие пользователи будут сразу заблокированы!
- Не регистрируйте больше одной учётной записи. Если у вас возникли проблемы при регистрации, то вы можете воспользоваться формой обратной связи внизу страницы.
- Регистрируйтесь с реально существующими E-mail адресами, иначе вы не сможете завершить регистрацию.
- Обязательно ознакомьтесь с правилами поведения на нашем форуме, чтобы избежать дальнейших конфликтов и непонимания.
С уважением, администрация форума Old-Games.RU
Комментарии
Сортировать комментарии по