【问题标题】:How to chunk text "from the back" in perl.如何在 perl 中“从后面”分块文本。
【发布时间】: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

标签: regex perl


【解决方案1】:

最佳测试:

use integer;
my $la = length($a);
my $r = $la % 8;
my @a = unpack(($r?"a$r":"")."(a8)".($la/8), $a);

似乎没有更清洁的方法可以有效地做到这一点。

解释:

use integer; 使得($la/8) 被截断为整数。 int($la/8) 会做同样的事情。

$r 是“余数”,将字符串“分割”成 8 个块后的剩余字符串量。

如果字符串能被 8 整除($r==0),则unpack 的模板中不能包含“余数”部分,否则"a$r"($r?"a$r":"")

unpack 模板的“商”或分块部分是:"(a8)".($la/8)

最后一行可以替换为下面的代码,以使代码看起来更清晰,但代价是增加了几个变量:

my $q = $la / 8;
my $tr = $r ? "a$r" : "";
my @a = unpack "$tr(a8)$q", $a;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 2013-08-21
    相关资源
    最近更新 更多