Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > array comparision

Reply
Thread Tools

array comparision

 
 
Marek
Guest
Posts: n/a
 
      08-16-2008


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";
}

 
Reply With Quote
 
 
 
 
Ben Morrow
Guest
Posts: n/a
 
      08-16-2008

Quoth Marek <(E-Mail Removed)>:
>
> 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

--
Like all men in Babylon I have been a proconsul; like all, a slave ... During
one lunar year, I have been declared invisible; I shrieked and was not heard,
I stole my bread and was not decapitated.
~ http://www.velocityreviews.com/forums/(E-Mail Removed) ~ Jorge Luis Borges, 'The Babylon Lottery'
 
Reply With Quote
 
 
 
 
h3xx
Guest
Posts: n/a
 
      08-16-2008
On Aug 16, 12:22*am, Marek <(E-Mail Removed)> wrote:
> 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";
}

 
Reply With Quote
 
h3xx
Guest
Posts: n/a
 
      08-16-2008
On Aug 16, 3:45*am, Ben Morrow <(E-Mail Removed)> wrote:
> Quoth Marek <(E-Mail Removed)>:
>
> but it would be better to use a module like Data::Compare
>
> * * use Data::Compare;
>
> * * my $same = Compare \@array3, \@array4;
>
> Ben


Nice! I didn't even know of that one.
 
Reply With Quote
 
Jürgen Exner
Guest
Posts: n/a
 
      08-16-2008
h3xx <(E-Mail Removed)> wrote:
>On Aug 16, 12:22*am, Marek <(E-Mail Removed)> wrote:


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

>
>/\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
 
Reply With Quote
 
Jürgen Exner
Guest
Posts: n/a
 
      08-16-2008
Marek <(E-Mail Removed)> wrote:

>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
 
Reply With Quote
 
Eric Pozharski
Guest
Posts: n/a
 
      08-16-2008
Marek <(E-Mail Removed)> wrote:

*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;


There's something strange. The left part of C<&&> isn't comparision.
It's assignment (you know).

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


L<Array::Compare>?

*CUT*

--
Torvalds' goal for Linux is very simple: World Domination
 
Reply With Quote
 
Ben Morrow
Guest
Posts: n/a
 
      08-16-2008

Quoth h3xx <(E-Mail Removed)>:
>
> # 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

--
'Deserve [death]? I daresay he did. Many live that deserve death. And some die
that deserve life. Can you give it to them? Then do not be too eager to deal
out death in judgement. For even the very wise cannot see all ends.'
(E-Mail Removed)
 
Reply With Quote
 
Marek
Guest
Posts: n/a
 
      08-17-2008

Thank you all for your great answers! I learned a lot!


greetigs from Munich


marek

 
Reply With Quote
 
Dr.Ruud
Guest
Posts: n/a
 
      08-17-2008
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

--
Affijn, Ruud

"Gewoon is een tijger."

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Comparision john VHDL 2 03-17-2005 10:37 PM
String comparision efficency Daniel Java 14 02-16-2005 09:01 AM
String Comparision Stephen ASP .Net 4 10-01-2004 12:52 PM
Date comparision zzyzx Java 10 07-24-2004 08:00 PM
stored procedure result comparision Viktor Popov ASP .Net 9 07-20-2004 08:50 PM



Advertisments