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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Парсинг без регулярных выражений 
:(
    Опции темы
dimdiden
Дата 29.12.2014, 09:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Привет всем! Помогите с, на мой взгляд нестандартной задачей.

Есть некий скаляр вида: 123adas433fdf545df5454
Вопрос как разбить эту строку на два массива: В первом первый элемент 123, второй 433, третий 545, т.е. только цифры. Во втором соответственно не цифры? Главное условие - не пользоваться регулярными выражениями и внешними модулями.

Вот на такой стадии сейчас

my $string = '123adas433fdf545df5454';
my @array = split '', $string;

#загнал каждый символ в массив

my @job = ();
$job[0] = ''";
my @job1 = ();
$job1[0] = ''";

#проинициализировал два массива для результатов и в них первый элемент

my $i = 0;
my $y = 0;

# $i и $y - переменные для определения элементов массива

foreach my $elem (@array) {                               # вот здесь и загвоздка. Цикл перебирает каждый элемент                  
     if (($elem ge 0)and($elem le 9)) {                   # массива array, если цифра - дописывает эту цифру к существующему
              $job[$i] = "$job[$i]$elem";                     # элементу [0] массива job, если нет - дописывает к [0] элементу job1 
          }                                                                  
     else {
              job1[$y] = "$job1[$y]$elem\n";
}
}
print "@job\n@job1";

Вопрос: как перескочить на следующий элемент массивов job и job1 для выполнения повторных действий?
$i++ и $y++ не подходят, так как плюсуют от каждого прохода элементов в цикле.

Заранее спасибо за помощь!


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


Опытный
**


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

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



А вас не смущает то, что критерий для разбиения в функции split это как раз регулярное выражение? То что вы там пишете пустую строку это уже детали. Получается что регулярка таки есть. Может вам смотреть в сторону unpack?
PM MAIL   Вверх
dimdiden
Дата 29.12.2014, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(infarch @  29.12.2014,  11:34 Найти цитируемый пост)
А вас не смущает то, что критерий для разбиения в функции split это как раз регулярное выражение?

Это скажем так единственное исключение.

Добавлено через 9 минут и 32 секунды
Цитата(infarch @  29.12.2014,  11:34 Найти цитируемый пост)
Может вам смотреть в сторону unpack? 


Предполагается что я не знаю сколько там цифр, букв. И вообще скаляр очень большой.

Мой алгоритм безвыходный?

PM MAIL   Вверх
ginnie
Дата 29.12.2014, 13:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



dimdiden, вот мой вариант:

Код

#!/usr/bin/perl

use strict;
use warnings;

sub save_substring (\@$$);

my $string = '123adas433fdf545df5454';

my %substrings = (number => {start => 0, length => 0}, string => {start => 0, length => 0});
my (@strings, @numbers);
my $string_length = length $string;

for (my $pos = 0; $pos < $string_length; $pos++) {
    my $char = substr($string, $pos, 1);
    if ($char ge '0' and $char le '9') {
        $substrings{number}{length}++ or $substrings{number}{start} = $pos;
        save_substring(@strings, $string, $substrings{string});
    }
    else {
        $substrings{string}{length}++ or $substrings{string}{start} = $pos;
        save_substring(@numbers, $string, $substrings{number});
    }
}

save_substring(@strings, $string, $substrings{string});
save_substring(@numbers, $string, $substrings{number});

print $string, "\n", join(', ', @strings), "\n", join(', ', @numbers), "\n";

sub save_substring (\@$$) {
    my ($array, $string, $substring) = @_;

    if ($substring->{length}) {
        push(@{$array}, substr($string, $substring->{start}, $substring->{length}));
        $substring->{length} = 0;
    }

    return;
}



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


Новичок



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

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



Если не против, задам вопросы, т.к. уровень очень слабый, прочитать до конца код не могу:
Цитата(ginnie @  29.12.2014,  13:00 Найти цитируемый пост)
my %substrings = (number => {start => 0, length => 0}, string => {start => 0, length => 0});

Здесь я так понимаю в хэше substrings инициализируются вложенные хэши number и string?
Цитата(ginnie @  29.12.2014,  13:00 Найти цитируемый пост)
$substrings{number}{length}++ or $substrings{number}{start} = $pos;

оператор or это ведь логическое "или". В этой строке идет инкрементация значения substrings{number}{length} или присваивание значению $substrings{number}{start} значения текущего $pos. Не могу прочитать эту строку.
Цитата(ginnie @  29.12.2014,  13:00 Найти цитируемый пост)
save_substring(@strings, $string, $substrings{string});

Здесь я так понимаю и происходит сохранение "кусочков" в необходимые по условию массивы. Объясни пожалуйста почему в цикле и за циклом присутствует эта строка кода. Поз. 18,22,26,27.
Про sub пока что и задавать нечего, изучаю этот вопрос.

Заранее сори что напрягаю!
PM MAIL   Вверх
ginnie
Дата 30.12.2014, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



В %substrings храним начальную позицию и длину числовой и символьной подстрок.

В случае, если очередной символ оказался цифрой, надо инкрементировать счетчик цифр $substrings{number}{length}++, если текущее значение счетчика 0, значит мы работаем с новой подстрокой и надо сохранить начальную позицию $substrings{number}{start} = $pos.

После начала новой подстроки нужно сохранить завершившуюся, для этого используется функция save_substring(). Она вызывается внутри цикла. Когда мы обработали все символы в строке цикл завершился, но одна из подстрок осталась не сохраненной (т.е. сохранение выполняется только при обнаружении новой подстроки). Поэтому после завершения цикла необходимо еще раз сохранить оставшиеся подстроки.

P.S. по причине смены места работы был в трех местах на собеседовании (Яндекс, Mail.ru и Rambler) и должен признать, что уровень у меня тоже слабоват  smile Но я не унываю, усиленно читаю Программирование на Perl (4 издание) и perldoc.perl.org, и Вы не должны унывать! Учитесь, тем более, что все возможности для этого у Вас есть!

Это сообщение отредактировал(а) ginnie - 30.12.2014, 17:47


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


Новичок



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

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



ginnie спасибо большое. Наконец я все понял, и даже про прототипы. Переделал код без них. Остался последний вопрос, что делает return в блоке функции? У брав его все работает и так. Подскажи пожалуйста!
PM MAIL   Вверх
ginnie
Дата 5.1.2015, 16:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



dimdiden, return используется в функции для указания возвращаемого значения. Я его стараюсь всегда писать, чтобы сразу было видно, какое значение возвращается (если return не использовать, вернется последнее вычисленное в функции значение). В данном случае возвращаемое значение мне не нужно, поэтому использую return без значения. 


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


Unregistered











Можно написать программку и попроще:

use strict;

my $string = '123adas433fdf545df5454';
my $m = -1;
my ($p,$g);
my (@strings, @numbers);

for (my $pos = 0; $pos < length($string); $pos++) {
    my $char = substr($string,$pos,1);
    $g = $p;
    $p = (($char ge '0') && ($char le '9'))? \@numbers: \@strings;
    $m++ if $p != $g;
    $p->[$m / 2] .= $char;
}

print "@strings @numbers";

Этот ответ добавлен с нового Винграда - http://vingrad.com
  Вверх
dimdiden
Дата 13.1.2015, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(gami @  7.1.2015,  22:06 Найти цитируемый пост)
$p = (($char ge '0') && ($char le '9'))? \@numbers: \@strings;


Цитата(gami @  7.1.2015,  22:06 Найти цитируемый пост)
  $p->[$m / 2] .= $char;


Подскажите кто то где почитать про вот эти ходы. Вот в первом выражении что означает знак вопроса и двоеточие после ссылки на numbers?
Во второй строчке вообще ничего не пойму.
Буду признателен за помощь.

Добавлено через 4 минуты и 20 секунд
Цитата(dimdiden @  13.1.2015,  16:21 Найти цитируемый пост)
Вот в первом выражении что означает знак вопроса и двоеточие после ссылки на numbers?


Стоять! Вышел на термин "тернарный оператор", сейчас покурю эту тему. Остальное под вопросом)
PM MAIL   Вверх
ginnie
Дата 13.1.2015, 16:46 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



dimdiden, $m - уменьшенный на 1 счетчик групп символов, $m/2 - индекс текущей группы в массивах (берется целая часть от деления на 2). 
Код

$p->[$m / 2] .= $char;

добавляет в конец текущей группы символ $char.


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


Новичок



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

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



Спасибо большое!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


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

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


 




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


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

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