Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何在Perl中检查两个数组是否包含相同的元素?_Arrays_Perl - Fatal编程技术网

Arrays 如何在Perl中检查两个数组是否包含相同的元素?

Arrays 如何在Perl中检查两个数组是否包含相同的元素?,arrays,perl,Arrays,Perl,所以我只需要一种简单的方法来判断两个数组在perl中是否相同。顺序不重要,所以我在寻找这样的东西: my@a=(1,2,3) my@b=(2,3,1) my@c=(1,2,4) 相同(@a,@b)返回1 相同(@a,@c)返回0 谢谢 如果您使用的是Perl 5.10或更高版本(如果不是,您真的应该升级),您可以使用: 使用严格; 使用警告; my@a=(1,2,3); my@b=(2,3,1); my@c=(1,2,4); #对它们进行排序(数字) @a=排序{$a$b}@a; @b=排序{$

所以我只需要一种简单的方法来判断两个数组在perl中是否相同。顺序不重要,所以我在寻找这样的东西:

my@a=(1,2,3)

my@b=(2,3,1)

my@c=(1,2,4)

相同(@a,@b)
返回1

相同(@a,@c)
返回0


谢谢

如果您使用的是
Perl 5.10
或更高版本(如果不是,您真的应该升级),您可以使用:

使用严格;
使用警告;
my@a=(1,2,3);
my@b=(2,3,1);
my@c=(1,2,4);
#对它们进行排序(数字)
@a=排序{$a$b}@a;
@b=排序{$a$b}@b;
@c=排序{$a$b}@c;
如果(@a~~@b){
打印“\@a和\@b相同!(排序后)\n”;
}
否则{
打印“否\n”;
}
如果(@a~~@c){
打印“\@a和\@c相同!(排序后)\n”;
}
否则{
打印“否\n”;
}
您还可以使用自己的功能:

use strict;
use warnings;

my @a = (1, 2, 3);
my @b = (2, 3, 1);
my @c = (1, 2, 4);

print same_elements(\@a, \@b) . "\n";
print same_elements(\@a, \@c) . "\n";

#arguments are two array references
sub same_elements {

    my $array_ref_1 = shift;
    my $array_ref_2 = shift;
    my @arr1 = @$array_ref_1;
    my @arr2 = @$array_ref_2;

    #If they are not the same length, we are done.
    if( scalar(@arr1) != scalar(@arr2) ) {

       return 0;
    }

    #sort them!
    @arr1 = sort { $a <=> $b } @arr1;
    @arr2 = sort { $a <=> $b } @arr2;

    foreach my $i( 0 .. $#arr1 ) {

        if ( $arr1[$i] != $arr2[$i] ) {
            return 0;
        }
    }
    return 1;
}
使用严格;
使用警告;
my@a=(1,2,3);
my@b=(2,3,1);
my@c=(1,2,4);
打印相同的元素(\@a,\@b)。“\n”;
打印相同的元素(\@a,\@c)。“\n”;
#参数是两个数组引用
次相同元素{
我的$array\u ref\u 1=移位;
我的$array\u ref\u 2=移位;
my@arr1=@$array\u ref\u 1;
my@arr2=@$array\u ref\u 2;
#如果它们的长度不一样,我们就完了。
if(标量(@arr1)!=标量(@arr2)){
返回0;
}
#把它们分类!
@arr1=排序{$a$b}@arr1;
@arr2=排序{$a$b}@arr2;
每个我的$i(0..$#arr1){
如果($arr1[$i]!=$arr2[$i]){
返回0;
}
}
返回1;
}

您可以在散列中计算元素的计数。创建一个(element=>count)散列,每次第一个数组包含该元素时,将计数向上提升,每次另一个数组包含该元素时,将计数向下提升(反之亦然)。如果两个数组具有所有相同的元素,则散列中的每个值都将为0

sub have_same_elements {
    my ($arr1, $arr2) = @_;
    my %counts = ();
    $counts{$_} += 1 foreach (@$arr1);
    $counts{$_} -= 1 foreach (@$arr2);
    return !(grep { $_ != 0 } values %counts);
}


$a_and_b_same = have_same_elements(\@a, \@b);  # will be true
$a_and_c_same = have_same_elements(\@a, \@c);  # will be false

(注意,这可能适用于或可能不适用于执行自身字符串化的对象。哈希键不能是引用,因此Perl会在使用它们时对引用进行字符串化。其默认字符串化器会将引用转换为类似于
数组(0x12345678)的内容)
,这会使引用不同,除非它们指向同一个东西。但是如果一个对象进行了自己的字符串化,并且没有为不同的引用返回不同的字符串,这可能会中断。正如您所知。)

首先,您必须重新考虑您的函数

 identical(@a, @b);
不向函数传递两个数组,而是传递一个数组,其中包含两个数组中的所有元素。你好像说:

identical(1, 2, 3, 2, 3, 1);
为了使函数正常工作,您必须将以下内容传递到阵列:

identical(\@a, \@b);
我想对你的子程序说,但这可能会让你觉得它会解决问题

如果顺序不重要,请在比较数组之前对其进行排序。你甚至可以作弊

sub identical {
   my $array_ref_1 = shift;
   my $array_fef_2 = shift;

   use Digest::SHA qw(sha1_hex);

   if ( ref( $array_ref_1 ) ne "ARRAY") or ( ref( $array_ref_2 ) ne "ARRAY") {
      return;   #Error, need two array references
  }

  # Dereference Arrays
  my @array_1 = @{$array_ref_1};
  my @array_2 = @{$array_ref_2};

  # Setup Arrays to be one big scalar
  my $scalar_1 = join "\n", sort @array_1;
  my $scalar_2 = join "\n", sort @array_2;

  my $checksum_1 = sha1_hex $scalar_1;
  my $checksum_2 = sha1_hex $scalar_2;

  if ($checksum_1 eq $checksum_2) {
     return 1;
  }
  else {
     return 0_but_true;
请注意:

  • 我可以在一条语句中取消引用、合并、生成校验和并进行比较。我把它们分开做是为了更清楚地说明我在做什么。从编程角度看,这可能没有任何区别。无论如何,Perl将优化整个过程。我总是追求清晰
  • 0\u但\u true
    返回0,但同时返回真值。通过这种方式,您可以执行类似于
    if(等同(\@A,\@B)){
    的操作,以确保函数正常工作。然后,您可以测试零或一
  • 一定要测试你的参数。我是用这个函数来做的
  • 我作弊了。我首先将两个排序数组转换为标量。然后,我使用sha1校验和验证它们是否相同。使用该函数的校验和应该很好。失败的可能性很小
真正的问题是,如果您有这样的多行阵列:

 @a = ("this", "that", "the\nother");
 @b = ("this", "that\nthe", "other");

使用
join
的方法会使结果的标量相等。

我想你可以这样写,对你正在处理的输入类型进行最少的假设(只需传递适当的比较子项):

其表现如下:

0> identical([0..100], [0..100])
$res[0] = 1

1> identical([0..100], ['0.0', 1..100])
$res[1] = ''

2> identical([0..100], ['0.0', 1..100], sub {shift == shift})
$res[2] = 1

3> identical(['0.66666666666', 0..10], [2/3, 0..10], sub {shift == shift})
$res[3] = ''

4> identical(['0.66666666666', 0..10], [2/3, 0..10], sub {shift() - shift() < 1e-5})
$res[4] = 1

# if you need this to be true check out https://stackoverflow.com/a/12127428/13992
5> identical([0..100], [List::Util::shuffle(0..100)])
$res[5] = ''
0>相同([0..100],[0..100])
$res[0]=1
1> 相同([0..100],'0.0',1..100])
$res[1]=''
2> 相同([0..100],'0.0',1..100],sub{shift==shift})
$res[2]=1
3> 相同(['0.666',0..10],[2/3,0..10],sub{shift==shift})
$res[3]=''
4> 相同(['0.666',0..10],[2/3,0..10],子{shift()-shift()<1e-5})
$res[4]=1
#如果你需要这是真的,请检查https://stackoverflow.com/a/12127428/13992
5> 相同([0..100],[List::Util::shuffle(0..100)])
$res[5]=''

您可能需要选择一个更好的名称。从定义上看,这些数组实际上都不相同(包括具有相同顺序的相同元素)。如果您不关心顺序,名称应该反映这一点。元素是否可以在数组中出现多次?
use List::Util;
sub identical {
  my @this = @{ +shift };
  my @that = @{ +shift };
  my $cmp = shift // sub { shift eq shift };
  return '' unless @this == @that;
  for my $idx (List::Util::shuffle keys @this) {
    return '' unless $cmp->($this[$idx], $that[$idx]);
  }
  return 1;
}
0> identical([0..100], [0..100])
$res[0] = 1

1> identical([0..100], ['0.0', 1..100])
$res[1] = ''

2> identical([0..100], ['0.0', 1..100], sub {shift == shift})
$res[2] = 1

3> identical(['0.66666666666', 0..10], [2/3, 0..10], sub {shift == shift})
$res[3] = ''

4> identical(['0.66666666666', 0..10], [2/3, 0..10], sub {shift() - shift() < 1e-5})
$res[4] = 1

# if you need this to be true check out https://stackoverflow.com/a/12127428/13992
5> identical([0..100], [List::Util::shuffle(0..100)])
$res[5] = ''