array comparision

M

Marek

Hello all!


I have several lines where I need to know whether the numbers are the
same or not.

I made an example, and my questions are inserted as comments:

Thank you for your help


marek


#! /usr/local/bin/perl

use warnings;
use strict;

my $line1 = "Mon, 04.08.2008 61126.10 79071.30 3567 2648.00 2864.00";
my $line2 =
"Die, 05.08.2008 7:40-19:40 12:00 61198.70 79103.40 3574 2648.00
2950.70 Name1";

my @array1 = split( /\t\s*/, $line1 );
my @array2 = split( /\t\s*/, $line2 );

my @array3;
for (@array1) { push @array3, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };
# do I really need a different array, to "slice out" my numbers?
# Is there not a more elegant (perlish) way to do this?
my @array4;
for (@array2) { push @array4, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };

my $same = 1;
$same = $same && @array3 == @array4;
# this compares only the number of elements of these arrays.
# how to iterate over each element and compare them?

if ($same) {
print "these numbers are the same!\n";
print join( "\t", @array3 );
print "\n";
print join( "\t", @array4 );
print "\n";
}
else {
print "these numbers are not the same!\n\n";
print join( "\t", @array3 );
print "\n";
print join( "\t", @array4 );
print "\n";
}
 
B

Ben Morrow

Quoth Marek said:
Hello all!


I have several lines where I need to know whether the numbers are the
same or not.

I made an example, and my questions are inserted as comments:

Thank you for your help


marek


#! /usr/local/bin/perl

use warnings;
use strict;

my $line1 = "Mon, 04.08.2008 61126.10 79071.30 3567 2648.00 2864.00";
my $line2 =
"Die, 05.08.2008 7:40-19:40 12:00 61198.70 79103.40 3574 2648.00
2950.70 Name1";

my @array1 = split( /\t\s*/, $line1 );
my @array2 = split( /\t\s*/, $line2 );

my @array3;
for (@array1) { push @array3, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };
# do I really need a different array, to "slice out" my numbers?
# Is there not a more elegant (perlish) way to do this?

Yes, you can use 'map', like this:

my @array3 =
map { /^\d+(?:\.\d+)?$/ ? $_ : () }
split /\t\s*/,
$line1;
my @array4;
for (@array2) { push @array4, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };

my $same = 1;
$same = $same && @array3 == @array4;
# this compares only the number of elements of these arrays.
# how to iterate over each element and compare them?

Well, the obvious way is

my $same =
@array3 == @array4 &&
!grep { $array3[$_] == $array4[$_] } 0..$#array3;

but it would be better to use a module like Data::Compare

use Data::Compare;

my $same = Compare \@array3, \@array4;

Ben
 
H

h3xx

Hello all!

I have several lines where I need to know whether the numbers are the
same or not.

I made an example, and my questions are inserted as comments:

Thank you for your help

marek

#! /usr/local/bin/perl

use warnings;
use strict;

my $line1 = "Mon, 04.08.2008       61126.10        79071.30        3567    2648.00 2864.00";
my $line2 =
"Die, 05.08.2008 7:40-19:40        12:00   61198.70       79103.40        3574    2648.00
2950.70 Name1";

my @array1 = split( /\t\s*/, $line1 );
my @array2 = split( /\t\s*/, $line2 );

/\s/ here will match any whitespace character. The \t is unnecessary.
my @array3;
for (@array1) { push @array3, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };
   # do I really need a different array, to "slice out" my numbers?
   # Is there not a more elegant (perlish) way to do this?
my @array4;
for (@array2) { push @array4, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };

my $same = 1;
$same = $same && @array3 == @array4;
  # this compares only the number of elements of these arrays.
  # how to iterate over each element and compare them?

if ($same) {
    print "these numbers are the same!\n";
    print join( "\t", @array3 );
    print "\n";
    print join( "\t", @array4 );
    print "\n";}

else {
    print "these numbers are not the same!\n\n";
    print join( "\t", @array3 );
    print "\n";
    print join( "\t", @array4 );
    print "\n";

}

Looks like you want to do it this way:

# find the numbers in the split arrays
my @nums1 = grep { /^\d+([:.]\d+)*$/ } @array1;
my @nums2 = grep { /^\d+([:.]\d+)*$/ } @array2;

# to be set upon first difference
my $fail = 0;

# check each member by the indexes
map {
$fail = 1 unless $nums1[$_] == $nums2[$_]
} 0 .. $#nums1;


if ($fail) {
    print "these numbers are not the same!\n\n",
    join ("\t", @array3),
"\n",
join ("\t", @array4),
"\n";
} else {
    print "these numbers are the same!\n",
    join ("\t", @array3),
"\n",
join ("\t", @array4),
"\n";
}
 
J

Jürgen Exner

h3xx said:
/\s/ here will match any whitespace character. The \t is unnecessary.

Depends on what the OP wants to match. /\t\s*/ and /\s*/ (and even /\s+/
for that matter) match different sets of strings. A plain /\s*/ neither
enforces a tab at the beginning nor at least one character.

jue
 
J

Jürgen Exner

Marek said:
for (@array1) { push @array3, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };

The match operator defaults to $_. No need to explicitely bind $_.
# do I really need a different array, to "slice out" my numbers?
# Is there not a more elegant (perlish) way to do this?

It appears to me as if you may be looking for grep():
@array3 = grep(/^\d+(?:\.\d+)?$/, @array1);
my $same = 1;
$same = $same && @array3 == @array4;
# this compares only the number of elements of these arrays.
# how to iterate over each element and compare them?

I am not sure I understand. Do you want to know if _all_ numbers are
equal (i.e. the arrays have the same content) or do you want to sort the
numbers into two groups based on equal/non equal?

If the former then just loop over them, either with a C-style loop or
with a foreach loop (assuming they are equal length):

for ($i = 0; $i < @array3, $i++) {
$same = $same && $array3[$i] == $array4[$i];
}

or

for (@array3){
$same = $same && $_ == shift @array4;
}

Or you can use map() in scalar context:
$diff= map( $array3[$_]==$array4[$_] ? ():(1), (0..$#array3));
print "All numbers are the same\n" unless $diff;

You can also use map() to get a list of indices for which the numbers
are equal or different although IMO grep() is the better candidate for
that:
grep($array3[$_]==$array4[$_], 0..$#array3);

If you rather want the values instead of the indices then just return
those from map():
@same = map( $array3[$_]==$array4[$_]? ($array3[$_]) : (),
0..$#array3);

jue
 
E

Eric Pozharski

*SKIP*
for (@array1) { push @array3, $_ if $_ =~ /^\d+(?:\.\d+)?$/ };

Be prepared to have problems with that naive parsing. I don't say that
that will fail for sure, but your data seems to be quite irregular.
There can be Easter Eggs.

Personally, I would match the whole line against complex RE with grabs
and then C<push @array1, [ $1, $2, $3 ]>. Though that's my personal
disease.

*SKIP*
$same = $same && @array3 == @array4;

# this compares only the number of elements of these arrays.
# how to iterate over each element and compare them?

L<Array::Compare>?

*CUT*
 
B

Ben Morrow

Quoth h3xx said:
# check each member by the indexes
map {
$fail = 1 unless $nums1[$_] == $nums2[$_]
} 0 .. $#nums1;

Why are you using map in void context? I know it works, but it's rather
bad style.

for (0..$#nums1) {
$fail = 1 unless $nums1[$_] == $nums2[$_];
}

Better would be to exit the loop early as soon as you know it will fail,
viz.

for (0..$#nums1) {
unless ($nums1[$_] == $nums2[$_]) {
$fail = 1;
last;
}
}

Ben
 
D

Dr.Ruud

Nonni Nil schreef:
Marek:
my @array1 = split( /\t\s*/, $line1 );

did you mean my @array1 = split( /[\t\s]*/, $line1 ); ?


Not very likely, because "[\t\s]" is equivalent to just "\s". You were
probably looking for "\s+", but you were losing that the TAB should be
at the start and that the full regex should match 1-or-more, not
0-or-more.

More likely, OP meant that the field separator is TAB, and the fields
have optional SPC's at the start.
So OP was probably looking for /\t */.

In two steps it is clearer:

my @values = split /\t/, $line; # FS is TAB
s/^ +// for @values; # ltrim
 
M

Marek

Yes Affijn, yes, my field separator is <TAB>. And just in case a field
is starting with a <space>, I added a \s*; but this was superfluous.
There are no spaces at the beginning. Thank you again for all your
very helpful answers :)


ps: my posting from 3rd August is still not answered :))) Just in
case you have some ideas again: "Debugger: Pipe print output into
shell" :)))
 
S

sheinrich

Hello all!

I have several lines where I need to know whether the numbers are the
same or not.

I made an example, and my questions are inserted as comments:

Thank you for your help

marek

#! /usr/local/bin/perl

use warnings;
use strict;

my $line1 = "Mon, 04.08.2008 61126.10 79071.30 3567 2648.00 2864.00";
my $line2 =
"Die, 05.08.2008 7:40-19:40 12:00 61198.70 79103.40 3574 2648.00
2950.70 Name1";

Just for the fun of Perl

$line1 =~ s/.*?\t\s*(\d+(\.\d+)?)/(.+?)$1/g;
print $line2 =~ /^$line1$/ ? "same\n" : "not same\n";

This however, requires a constant decimal notation and wouldn't help
you much if you always need your numbers for a closer inspection.
Still it might be the 'perlish' way that helps find the occasional
discrepancy.


Regards, Steffen
 
W

Willem

Ben Morrow wrote:
)
) Quoth h3xx <[email protected]>:
)>
)> # check each member by the indexes
)> map {
)> $fail = 1 unless $nums1[$_] == $nums2[$_]
)> } 0 .. $#nums1;
)
) Why are you using map in void context? I know it works, but it's rather
) bad style.
)
) for (0..$#nums1) {
) $fail = 1 unless $nums1[$_] == $nums2[$_];
) }

True.

) Better would be to exit the loop early as soon as you know it will fail,
) viz.
)
) for (0..$#nums1) {
) unless ($nums1[$_] == $nums2[$_]) {
) $fail = 1;
) last;
) }
) }

If you look further you will see he then prints all differing numbers.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top