2014-01-26 4 views
0

У меня есть строка, которая выглядит примерно так:Извлечение строки из сложной системы кронштейном

(((Q,(P,(O,(M,N)))),(B,A)),C) 

И я хочу, чтобы сгруппировать письмо внутри кронштейна, как это:

1|MN 
2|MNO 
3|MNOP 
4|MNOPQ 
5|BA 
6|MNOPQBA 
7|MNOPQBAC 

Как я могу сделать что? Я новичок в программировании и начинаю писать в Perl, любая помощь будет оценена по достоинству. Благодаря!

+2

Добро пожаловать в Stack Overflow! Пожалуйста, найдите минутку, чтобы прочитать [ask] документацию.Несмотря на то, что ваш вопрос касается темы, касающейся программирования, он просит нас полностью решить вашу проблему. Он также очень похож на домашнее задание. Нет ничего плохого в домашней работе, но вы должны думать об этом сами. Обманывать, позволяя кому-то решить проблему, укусит вас позже. Пожалуйста, подумайте о том, как это можно сделать. Просто подумайте о подходе/алгоритме и напишите это, если вы не можете сделать это в Perl. Мы ценим усилие здесь. :) – simbabque

ответ

4

Написать простой парсер:

sub parse { 
    my ($string_ref) = @_; 

    # check if the remaining string is a (x,y) group 
    if ($$string_ref =~ s/\A[(]//) { 
    my $first = parse($string_ref); 
    $$string_ref =~ s/\A[,]// or die "Expected a comma [,]"; 
    my $second = parse($string_ref); 
    $$string_ref =~ s/\A[)]// or die "Expected a closing paren [)]"; 
    return [$first, $second]; 
    } 
    # check if we have a simple string 
    elsif ($$string_ref =~ s/\A([^,()]+)//) { 
    return $1; 
    } 
    else { 
    die "Expected [(] or [^,()]"; 
    } 
} 

Это подпрограмма, которая называет себя для вложенных частей. Он ссылается на строку. Чтобы получить строку внутри этой ссылки, мы должны разыменовать ее: $$reference. Чтобы создать ссылку, мы используем оператор \: $reference = \$value.

=~ s/.../.../ применяет замену на строку. В шаблоне \A закрепляет в начале строки, тогда как [...] - это класс символов . Поскольку вторая часть нашей подстановки пуста, соответствующая часть в начале строки удаляется.

Теперь my $str = "(((Q,(P,(O,(M,N)))),(B,A)),C)"; parse(\$str) производит эту структуру данных:

[[["Q", ["P", ["O", ["M", "N"]]]], ["B", "A"]], "C"] 

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

sub flatten { 
    my ($data) = @_; 

    if (ref $data eq 'ARRAY') { 
    my ($first, $second) = @$data; 
    my ($first_str, @first_others) = flatten($first); 
    my ($second_str, @second_others) = flatten($second); 
    my $str = $first_str . $second_str; 
    my @others = (@first_others, @second_others, $str); 
    return $str, @others; 
    } 
    elsif (ref $data eq '') { 
    return $data; 
    } 
    else { 
    die "Unknown data type ", ref $data; 
    } 
} 

ref встроенный возвращает тип ссылки. Если результатом является пустая строка, то значение не является ссылкой (в этом случае это была бы простая строка). Вышеприведенный код широко использует назначение списка: ($x, @y) = (1, 2, 3) присваивает номера так, чтобы $x = 1 и @y = (2, 3). Это также работает, когда числа меньше - ($x, @y) = (1), @y будет пустым. Также обратите внимание, что мы возвращаем либо одно значение (при выравнивании строки), либо несколько значений (при выравнивании содержимого паренов).

Применительно к этой структуре данных, мы получаем список:

(
    "QPOMNBAC", 
    "MN", 
    "OMN", 
    "POMN", 
    "QPOMN", 
    "BA", 
    "QPOMNBA", 
    "QPOMNBAC", 
) 

Так как мы можем получить на выходе вы хотели?

use feature 'say'; 

my ($whole_string, @parts) = flatten(parse(\$str)); 

for my $i (0 .. $#parts) { 
    say $i + 1, "|", $parts[$i]; 
} 

Который производит

1|MN 
2|OMN 
3|POMN 
4|QPOMN 
5|BA 
6|QPOMNBA 
7|QPOMNBAC 

упорядочении внутри строки отличается хотели - вы, кажется, сортировали части в каждой почти круглые скобки в алфавитном порядке. Для этого нам нужно было что-то изменить внутри flatten. Но, не зная, как именно вы хотите сортировать, это невозможно сделать.

+0

Аккуратное объяснение! Вы едете в [GPW] (http://act.yapc.eu/gpw2014/) в этом году? – simbabque

+0

@simbabque Спасибо. Я не совсем уверен, пойду ли я, но я, конечно, хотел бы приехать. Когда регистрация будет закрыта? – amon

+0

Bitte schreib mir ne Mail meine hannover.pm Addresse. – simbabque

0

Снимите запятые и обеспечить результат в качестве аргумента функции чтения любого (в основном) шепелявостью :)

Смежные вопросы