在 perl 中使用嵌套映射是一种好习惯吗?

Posted

技术标签:

【中文标题】在 perl 中使用嵌套映射是一种好习惯吗?【英文标题】:Is using nested map in perl a good practice? 【发布时间】:2012-10-06 16:33:40 【问题描述】:
my @c= map 
        my $v=$_;
        map $_ * $v  @m
 @a;

这样使用map 是个好习惯吗?为什么不? 如果没有,还有其他方法吗?

【问题讨论】:

不要像for-loop那样使用map,它是列表修饰符。 map 不仅是一个列表修饰符,还是一个列表生成器。这就是他的例子所显示的。不过,您的评论对于 map print @list 之类的内容是正确的。 @Moritz,“列表修饰符”是一个非常适用的术语。 map 输出的列表直接基于传递给它的列表。 (不过,我同意其余的观点。map 不会在 void 上下文中被调用。) 我在 void 上下文中看到很多关于 map 的 cmets,但我很确定我已经读到该构造中的性能问题已得到修复。 ***.com/a/4174537/468327(p.s.此评论与可读性无关) @ikegami 好的,授予。我在想这样一个事实,即在地图内部 $_ 是一个允许修改原始列表的别名。含义@l = (1, 2); map $_ += 1 @l; # @l is now (2, 3) 【参考方案1】:

嵌套map 与任何其他嵌套结构具有相同的问题和相同的解决方案,除了因需要重新分配$_ 而略有放大。嵌套的map 不流动的事实是代码异味:您的代码试图告诉您应该稍微不同的结构。

并且适当的更改是将内部操作变成函数调用,这样读者就不必同时跟踪两个作用域。在这种情况下,您会得到:

sub scale 
    my ($factor, @numbers) = @_;

    return map  $factor * $_  @numbers;


my @c = map  scale($_, @m)  @a;

【讨论】:

这里有很多设置/拆卸,您对sub scale my $factor = shift; return map $factor * $_ @_ 满意吗? 当然;这几乎是一个风格问题。我倾向于始终使用一种或另一种形式,除非我的分析告诉我一致性会影响性能,但这真的只是我自己。【参考方案2】:

我一直对map 命令有复杂的感觉。使用map 有很多陷阱,这也是让 Python 人对 Perl 的不可读性幸灾乐祸的原因之一。此外,map 并不比使用常规循环更有效。

当 map 修改 $_ 的值时,有一个 gotcha,因为它实际上只是原始数组中值的别名。修改$_,你就修改了你原来的数组。也许这就是您想要的,但 map 命令可能会掩盖这一点。 Perl Monks 中有一个关于 map 的讨论。

即使您在map 中使用map 确实有效(map 确实为您本地化了$_,所以$_ 在一个map 中与$_ 中的不同其他map),还有可读性和可维护性的问题。

只有在用法清晰且易于理解上下文时才使用map。保存电子邮件签名的聪明 Perl 技巧。我不会使用地图内地图。

【讨论】:

我明白你关于 python 感知的观点,但我发现列表推导同样难以理解。 那个“陷阱”也适用于for,以及所有列表元素有别名的循环结构。这不是特定于map,而是可能特定于perl。我也不同意map 包含陷阱,也许您应该通过一些示例来验证该声明。 这不是错误。这是一个特点!看到它是documented!当你在文档中看到描述副作用的词 bizarre 时,你就有问题了。当你必须做一些奇怪的语法咒语,以便 Perl 可以正确解析你的语句时,你就有了陷阱。将 map 的文档与 Foreach loops 的文档进行比较。此外,双地图将是一个维护头痛。当你必须开始像编译器一样思考时,你就有问题了。 单词“bizarre”被限定为“如果 LIST 的元素不是变量”。这同样适用于 for 循环。试试perl -e 'print ++$_ for 1,2,3'。你提到的这些“奇怪的语法咒语”是什么?【参考方案3】:

我无法回答这是否是好的做法。一般来说,在很多情况下,我会大量使用嵌套地图。它很简短,简洁明了。

然而,这样的嵌套地图总是有变得有点太大和笨拙的危险,在这种情况下它们变得比它们必须的更难阅读($_ 在这种情况下指的是哪个列表!?)。所以使用它们,是的,但要谨慎使用——就像所有其他使 Perl 如此简洁和富有表现力的类似事物一样。

【讨论】:

【参考方案4】:

我不确定你的意思。它会很好地工作,还是您在询问可读性?与等效的 foreach 循环相比,阅读较长的 map 可能会更加困难。

my @c;
for my $v (@a) 
   push @c, map  $_ * $v  @m;

【讨论】:

执行时间如何? loopmap 哪个更快?如果我使用 perl 脚本进行大量数据处理,loop 会减慢执行速度吗?在这种情况下map 会更好吗?

以上是关于在 perl 中使用嵌套映射是一种好习惯吗?的主要内容,如果未能解决你的问题,请参考以下文章

将对象文字用作哈希表是一种好习惯吗?

在“for”循环条件中使用“三元运算”是一种好习惯吗?

使用“视图”进行分组是一种好习惯吗?

使用引用来布置简单的功能是一种好习惯吗

在整个应用程序中使用此 NSManagedObjectContext 是一种好习惯吗

尝试使用资源文件编写器是一种好习惯吗