如何在Perl中检查数组的所有元素是否相同?

som*_*ody 11 arrays perl

我有一个阵列@test.检查数组中每个元素是否是同一个字符串的最佳方法是什么?

我知道我可以通过foreach循环来实现它但是有更好的方法吗?我检查了地图功能,但我不确定这是否是我需要的.

Eug*_*ash 14

如果字符串已知,则可以grep在标量上下文中使用:

if (@test == grep { $_ eq $string } @test) {
 # all equal
}
Run Code Online (Sandbox Code Playgroud)

否则,使用哈希:

my %string = map { $_, 1 } @test;
if (keys %string == 1) {
 # all equal
}
Run Code Online (Sandbox Code Playgroud)

或更短的版本:

if (keys %{{ map {$_, 1} @test }} == 1) {
 # all equal
}
Run Code Online (Sandbox Code Playgroud)

注意:当在Perl中用作字符串时,undefonined值的行为类似于空字符串("").因此,如果数组只包含空字符串和undefs ,则检查将返回true .

这是一个考虑到这一点的解决方案:

my $is_equal = 0;
my $string   = $test[0]; # the first element

for my $i (0..$#test) {
    last unless defined $string == defined $test[$i];
    last if defined $test[$i] && $test[$i] ne $string;
    $is_equal = 1 if $i == $#test;
}
Run Code Online (Sandbox Code Playgroud)

  • 坏.即使第一个元素不匹配,您也总是需要遍历整个数组. (3认同)
  • @codeholic:只有当数组可能异常大时才会出现"Bad".对于较短的阵列,grep是要走的路. (2认同)

Sin*_*nür 10

如果,接受的帖子中的两种方法都会给你错误的答案@test = (undef, '').也就是说,它们声明一个未定义的值等于空字符串.

这可能是可以接受的.此外,使用grep遍历数组的所有元素,即使在早期发现不匹配并且使用散列比使用数组元素所使用的内存多一倍.如果您有小数组,这些都不会成为问题.并且,grep对于合理的列表大小,可能足够快.

但是,这里有一个替代方案,1)返回false,(undef, '')并且(undef, 0),2)不会增加程序的内存占用,3)一旦发现不匹配就会发生短路:

#!/usr/bin/perl

use strict; use warnings;

# Returns true for an empty array as there exist
# no elements of an empty set that are different
# than each other (see
# http://en.wikipedia.org/wiki/Vacuous_truth)

sub all_the_same {
    my ($ref) = @_;
    return 1 unless @$ref;
    my $cmpv = \ $ref->[-1];
    for my $i (0 .. $#$ref - 1)  {
        my $this = \ $ref->[$i];
        return unless defined $$cmpv == defined $$this;
        return if defined $$this
            and ( $$cmpv ne $$this );
    }
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

但是,使用List :: MoreUtils :: first_index可能会更快:

use List::MoreUtils qw( first_index );

sub all_the_same {
    my ($ref) = @_;
    my $first = \ $ref->[0];
    return -1 == first_index {
        (defined $$first != defined)
            or (defined and $_ ne $$first)
    } @$ref;
}
Run Code Online (Sandbox Code Playgroud)