【发布时间】:2015-11-15 16:20:05
【问题描述】:
我正在编写代码以将 perl 中“从后面”(即从头到尾或从右到左)中的(大)文本字符串分成大小相等的块(其余部分在前面)。
它正在工作,但这似乎是 perl 的“做(概念上)简单的事情很容易/快速”范式正在崩溃的情况。
我发现的最优雅的方式改编自这里: How do I display large numbers with commas? HTML
my @a = split /(?=(?:.{8})+$)/,$a;
但这很慢,因为字符串变得非常大,可能是由于所有必要的回溯。使用相同的想法(或任何正则表达式)是否有更有效的方法?
出于类似的低效率问题,我拒绝了“反向输入,正向处理,反向输出”的想法。但如果有人对此有所了解,我欢迎纠正这些问题。
我确实做了一个蛮力的“substr 迭代”实现,这很好但不优雅。
使用 unpack 的实现只是稍微不那么优雅但也稍微快了一点,我目前正在运行,改编自这里:Split a String into Equal Length Chunk in Perl
use integer;
my $la = length($a);
my $r = $la % 8;
my @a = unpack(($r?"a$r":"")."(a8)"x($la/8), $a);
很丑。即使是看似简化的"(a8)*"(而不是x)也失败了,因为由于某种原因,在长度小于8(比如5)的情况下,perl 最后会给出一个额外的"",并且解包模板是"a5(a8)*" . (有人对那个“功能”有解释吗?:-S)
在不引入低效率的情况下简化任何更好的想法?谢谢。
【问题讨论】:
-
如果有人感兴趣,应用程序是 bignum 算术,在可能的情况下使用分块进行“原生”算术。
-
在这种情况下,您是否考虑过向后存储您的号码? :)
-
@hobbs 是的,这是我最新的想法——只是在内部将所有内容向后表示。直到我意识到我必须重新反转每个操作的参数(内循环)才能将它们提供给“本机”算术。有点违背目的。
-
我发现了一点改进:
(a8)周围的括号是多余的。 (括号是(a8)*留下的)。 -
@JeffY,因为你关心性能,并且任务可以用
unpack解决... IME 在 Perl 中处理原始数据时没有什么比pack/unpack更快的了(除了自定义 XS)。是的,它看起来很难看,但这可以通过将代码移动到函数中来解决。 (基准:pastebin.com/eByQ4z3S)