比较字符串中包含的2组数字

时间:2016-07-15 16:32:44

标签: perl

我有2个标量如下:

$a = '100 105 010';
$b = '010 105 100';

如果两者具有相同的值集,我如何比较?订单没关系。 一种方法是按升序排列并进行比较,有更好的方法吗?

4 个答案:

答案 0 :(得分:0)

没有模块,你可以使用哈希:

#!/usr/bin/perl
use warnings;
use strict;

my $x = '100 105 010 2';
my $y = '010 105 100 100 1';

my (%hx, %hy);
$hx{$_}++ for split ' ', $x;
$hy{$_}++ for split ' ', $y;

for my $k (keys %hx) {
    if (! exists $hy{$k}) {
        print "$k missing in y\n";

    } elsif ($hy{$k} != $hx{$k}) {
        print "$k has different number of occurences\n";
    }
    delete $hy{$k};
}
print "$_ missing in x\n" for keys %hy;

$a$bsort中使用的特殊变量,因此我将其重命名为$x$y

split将字符串转换为列表。每个哈希计算成员在列表中出现的次数。

另见Perl FAQ 4

答案 1 :(得分:0)

您可以将每个字符串拆分为一个数组,然后对数组进行排序和比较。手工:

use warnings;
use strict;

my $x = '100 105 1 010';
my $y = '010 105 100 2';

my @xs = sort { $a <=> $b } split ' ', $x;
my @ys = sort { $a <=> $b } split ' ', $y;

if (@xs != @ys) {
    print "Differ in number of elements.\n";
}
else {
    for (0..$#xs) {
        print "Differ: $xs[$_] vs $ys[$_]\n" if $xs[$_] != $ys[$_];
    }
}

# For boolean comparison put it in a sub
print arr_num_eq(\@xs, \@ys), "\n";    

sub arr_num_eq {
    my ($ra, $rb) = @_;
    return 0 if @$ra != @$rb;
    $ra->[$_] != $rb->[$_]  && return 0  for 0..$#$ra; 
    return 1;
}

排序也可以移动到sub,然后接受字符串。它的方式也可用于比较现有的数组。请添加参数检查。

有许多模块具有此功能。来自permArray::Compare隐藏了上面的排序,但内部将排序的数组连接成字符串,因此我们从字符串开始重复了这里的工作。 List::AllUtils当然也提供了很长的实用程序列表。

例如,请参阅this post,了解一些方法(不是智能匹配 ~~),如果效率问题,请参阅基准测试。

使用Array::Compare中提到的实施构思,每个评论ysth

sub str_num_eq {
    return join(' ', sort { $a <=> $b } split / /, $_[0]) 
        eq join(' ', sort { $a <=> $b } split / /, $_[1])
}

最合适的方法取决于它的用途和使用方法。它只是一个布尔比较,或者如果发现它们不同会更多吗?它是如何在您的程序流程中出现的?什么是典型的字符串大小,它的运行频率是多少?字符串通常是相同还是不同,它们通常会有很大差异吗?等

答案 2 :(得分:0)

其他尝试使用模式匹配,

这不是直截了当但它会起作用。

按标量值的任何人构造模式。然后按构造的模式检查另一个字符串。

my $a = '100 100 105';
my $b = '100 105 100';

my @b_ary = split(" ",$b);
my $regex =  join'\b|\b', @b_ary;

my $word_length = @b_ary * 2 - 1; #Count the number of words and space. 
my $rgx = qr"^(?:\b$regex\b|\s){$word_length}$"; #`{n}` match word exact n times 

if($a=~m/$rgx/)
{
    print "same values\n";
}
else
{
    print "Not a same values\n";
}

答案 3 :(得分:0)

上面已经公布了答案。这是为了防止您想要删除空格并比较每个数字。

$x = '100 105 010';
$y = '010 105 100';
join("",sort split "",join("",split " ",$x)) eq join("",sort split "",join("",split " ",$y));