Difference between two values in a column in Perl

V

venkateshwar

Hi,

I have a large set of values like this in two different columns,both
the values are variables..

I need to check if first value(ValA) is same in any of the consecutive
values and then find the difference between valB of those two matched
valA! and the next instant the difference should be between the valB
of second one with third match.

For example in this set, 9 appears thrice. first time, the difference
shd be printed as 3099 - 3000, the next time, it should be printed as
5098 - 3099.

valA,valB
9,3000
10,3010
1,3011
2,1020
3,3001
4,4010
9,3099
5,4011
18,4020
19,2044
20,3098
9,5098

How do I do this in Perl??

regards
venkat.
 
M

Martijn Lievaart

Hi,

I have a large set of values like this in two different columns,both the
values are variables..

I need to check if first value(ValA) is same in any of the consecutive
values and then find the difference between valB of those two matched
valA! and the next instant the difference should be between the valB of
second one with third match.

For example in this set, 9 appears thrice. first time, the difference
shd be printed as 3099 - 3000, the next time, it should be printed as
5098 - 3099.

valA,valB
9,3000
10,3010
1,3011
2,1020
3,3001
4,4010
9,3099
5,4011
18,4020
19,2044
20,3098
9,5098

Put the values in an array of arrays, e.g.

my @vals=( [9,3000], [10, 3010] ... etc

(reading this in from a file is left as an exercise for the interested
reader)

Keep track of which values you have seen sofar.

my %seen;

Iterate over the array, skipping any values you have already seen.

for my $t (@vals) {
my ($valA, $valB) = @{$t};
last if %seen{$valA};
%seen{$valA}=1;

Find all entries that have the same valA.

my @allAs = grep { $_->[0] == $valA } @vals;

Iterate over this array.

my $last = shift @allAs;
while (defined(my $cur = shift @allAs)) {
print "$valA => $cur-$last\n";
$last = $cur;
}
}

All untested, full of syntax errors, possibly a few thinkos, but it
should get you started.

HTH,
M4
 
M

Mirco Wahab

venkateshwar said:
For example in this set, 9 appears thrice. first time, the difference
shd be printed as 3099 - 3000, the next time, it should be printed as
5098 - 3099.

valA,valB
9,3000
10,3010
1,3011
2,1020
3,3001
4,4010
9,3099
5,4011
18,4020
19,2044
20,3098
9,5098

How do I do this in Perl??

There are 100'es of possible solutions
in Perl, depending on the raw data
source, format, size etc.

One variant (data in a simple scalar)
would include:

...
# valA,valB
my $columns='
9,3000
10,3010
1,3011
2,1020
3,3001
4,4010
9,3099
5,4011
18,4020
19,2044
20,3098
9,5098
';
my %helper;
...

A 'helper' hash which elements contain
Arrays of the corresponding numbers,
lets put them in:

...
push @{ $helper{$1} }, $2
while $columns=~/\D*(\d+)\D*(\d+)/g;
...

Now, the keys of the hash %helper are
the 'first column', the values did
accumulate the second column on the
right place.

Now we can go through the hash and
find the differences:

...
map {
my $last = 0;
print "\n$_ ==> ";
for my $el ( @{$helper{$_}} ) {
print "$el - $last, ";
$last = $el
}
}
grep @{$helper{$_}} > 1,
keys %helper;
...

This must be read 'upwards', starts with
extracting the keys (first column), filtering
out those keys, which don't have more than
one value entry (the 'grep' line), the
remaining (one (9) in your case is brought
into the map {} block. There, the array
of values of the {9}-key is simply
looped through in order to see what it
contains (and printed).

This is intended as a 'building block'
only, (although it does work with your data),
the map should return an array of the
differences you need in each pass.

Regards

M.
 

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
474,204
Messages
2,571,063
Members
47,670
Latest member
micheljon

Latest Threads

Top