我有一个看起来像这样的字符串:
(((Q,(P,(O,(M,N)))),(B,A)),C)
我想将这个字母分组在括号内:
1|MN
2|MNO
3|MNOP
4|MNOPQ
5|BA
6|MNOPQBA
7|MNOPQBAC
我该怎么做?我是编程并开始用Perl编写的新手,任何帮助都会受到赞赏。谢谢!
答案 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的读取函数:)