1. Друзья, в это тяжёлое и непонятное для всех нас время мы просим вас воздержаться от любых упоминаний политики на форуме, - этим ситуации не поможешь, а только возникнут ненужные ссоры и обиды. Это касается также шуток и юмора на тему конфликта. Пусть войны будут только виртуальными, а политики решают разногласия дипломатическим путём. С уважением, администрация Old-Games.RU.

    Скрыть объявление
  2. Если Вы видите это сообщение, значит, вы ещё не зарегистрировались на нашем форуме.

    Зарегистрируйтесь, если вы хотите принять участие в обсуждениях. Перед регистрацией примите к сведению:
    1. Не регистрируйтесь с никами типа asdfdadhgd, 354621 и тому подобными, не несущими смысловой нагрузки (ник должен быть читаемым!): такие пользователи будут сразу заблокированы!
    2. Не регистрируйте больше одной учётной записи. Если у вас возникли проблемы при регистрации, то вы можете воспользоваться формой обратной связи внизу страницы.
    3. Регистрируйтесь с реально существующими E-mail адресами, иначе вы не сможете завершить регистрацию.
    4. Обязательно ознакомьтесь с правилами поведения на нашем форуме, чтобы избежать дальнейших конфликтов и непонимания.
    С уважением, администрация форума Old-Games.RU
    Скрыть объявление

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

Автор: Helmut · 15 окт 2020 ·
  1. Понадобилась тут функция сортировки массива. Что-то типа 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;
    }
    
    kreol и Dragoon нравится это.

Комментарии

Чтобы оставить комментарий просто зарегистрируйтесь и станьте участником!
  1. На этом сайте используются файлы cookie, чтобы персонализировать содержимое, хранить Ваши предпочтения и держать Вас авторизованным в системе, если Вы зарегистрировались.
    Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie.
    Скрыть объявление