我有一个包含n
个元素的数组。因此,每个元素可能会在开头或结尾有空格。所以我想一次删除空格。这是我的代码片段,它可以工作,也可以不工作(不工作的代码可以在元素的末尾修剪,但不能从元素的前端修剪)。
不工作:
....
use Data::Dumper;
my @a = ("String1", " String2 ", "String3 ");
print Dumper(\@a);
@a = map{ (s/\s*$//)&&$_}@a;
print Dumper(\@a);
...
工作中:
...
use Data::Dumper;
my @a = ("String1", " String2 ", "String3 ");
print Dumper(\@a);
my @b = trim_spaces(@a);
print Dumper(\@b);
sub trim_spaces
{
my @strings = @_;
s/\s+//g for @strings;
return @strings;
}
...
不知道这两个有什么不同。
如果有更好的建议,请与我分享!
发布于 2020-04-27 14:16:49
您的“不工作示例”仅从字符串的一端删除空格。表达式s/^\s+|\s+$//g
将删除两端的空格。
您可以通过使用/r
标志返回修改后的副本来改进代码:
@a = map { s/^\s+|\s+$//gr } @a;
或者,如果您必须执行以下操作:
@a = map { s/^\s+|\s+$//g; $_ } @a;
发布于 2020-04-27 14:26:31
这个块有两个问题:
{ (s/\s*$//)&& $_ }
一个微不足道的问题是,它只删除了尾随空格,而不是前导,您说过您也想删除它。
更隐蔽的问题是对&&
的误导使用。如果s///
中的正则表达式没有找到匹配项,它将在&&
的左侧返回undef
;这意味着不会执行右侧的值,而undef
将成为整个块的值。这意味着正则表达式不匹配的任何字符串都将被删除,并替换为map
返回的结果数组中的undef
,这可能不是您想要的结果。
这实际上不会发生在您编写的正则表达式中,因为每个字符串都与\s*
匹配,并且s///
仍然返回true,即使它实际上没有修改字符串。但这取决于正则表达式和一个不好的假设。
更广泛地说,您的方法混合并匹配了两种不兼容的数据修改方法:就地变异(s///
)和应用了某些更改的创建副本(map
)。
map
函数旨在创建一个新数组,该数组的元素以某种方式基于输入数组;理想情况下,它不应在此过程中修改原始数组。但是您的代码需要这样做-即使您没有将map的结果分配回@a
,s///
也会就地修改@a
中的字符串。实际上,您可以从代码中删除@a =
并获得相同的结果。这不被认为是良好的实践;map
应该用于其返回值,而不是副作用。
如果您想就地修改数组的元素,那么您的for
解决方案实际上是可行的。它清楚地表明了你在做什么,副作用也是可以的。
如果您希望保留原始数组并应用更改创建一个新数组,则应在替换项上使用/r
标志,这会使它们返回结果字符串,而不是原地修改原始数组:
my @b = map { s/^\s+|\s+$//gr } @a;
这将使@a
保持原样,并使用修剪后的字符串创建一个新的数组@b
。
https://stackoverflow.com/questions/61460830
复制