从复杂的支架系统中提取字符串

时间:2014-01-26 09:02:05

标签: perl

我有一个看起来像这样的字符串:

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

我想将这个字母分组在括号内:

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

我该怎么做?我是编程并开始用Perl编写的新手,任何帮助都会受到赞赏。谢谢!

2 个答案:

答案 0 :(得分: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为空。另请注意,我们返回单个值(展平字符串时)或多个值(展平parens内容时)。

应用于该数据结构,我们得到列表:

(
  "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

字符串内部的排序与想要的不同 - 您似乎几乎按字母顺序对每个parens中的部分进行了排序。为此,我们必须更改flatten内的内容。但是如果不知道你想要如何排序,这是不可能做到的。

答案 1 :(得分:0)

删除逗号并将结果作为参数提供给任何(主要)lisp的读取函数:)