Merging sparse arrays

S

Samwyse

I have two arrays of equal length that contain null values. I want one
array with fewer nulls. This almost works:

push @t, shift(@f).shift(@g) while scalar @f;

except that every once in a while both arrays have values in the same
slot. This won't work at all:

push @t, shift(@f)||shift(@g) while scalar @f;

because the || operator short-circuits. Can anyone do this in one line,
or do I need do it the hard way:

while (scalar @f) {
($a, $b) = (shift(@f), shift(@g));
push @t, $a || $b;
}
 
P

Paul Lalli

Samwyse said:
I have two arrays of equal length that contain null values. I want one
array with fewer nulls. This almost works:

push @t, shift(@f).shift(@g) while scalar @f;

except that every once in a while both arrays have values in the same
slot. This won't work at all:

push @t, shift(@f)||shift(@g) while scalar @f;

because the || operator short-circuits. Can anyone do this in one line,
or do I need do it the hard way:

while (scalar @f) {
($a, $b) = (shift(@f), shift(@g));
push @t, $a || $b;
}

I don't especially understand your goal, but what about...

push @t, $f[$_] || $g[$_] for 0..$#f;

? Your description gave no requirement that @f or @g had to be
depleted by the expression...

You might also find one or more of List::MoreUtils's functions handy:
@t = pairwise { $a || $b } @f, @g;

I have to point out that your problem description is incomplete at best
- you said your first solution only "almost" works, because the two
arrays might have defined values in the same "slot"... but you never
said what you want to happen in that case. Please see the Posting
Guidelines for this group. They will instruct you to, at a minimum,
post sample input and desired output.

Hope this helps,
Paul Lalli
 
A

Anno Siegel

Samwyse said:
I have two arrays of equal length that contain null values. I want one
array with fewer nulls. This almost works:

push @t, shift(@f).shift(@g) while scalar @f;

except that every once in a while both arrays have values in the same
slot. This won't work at all:

push @t, shift(@f)||shift(@g) while scalar @f;

because the || operator short-circuits. Can anyone do this in one line,
or do I need do it the hard way:

while (scalar @f) {
($a, $b) = (shift(@f), shift(@g));
push @t, $a || $b;
}

One way:

my @t = map shift @g || $_, @f;

That consumes @g but leaves @f intact.

Anno
 
X

Xicheng

Samwyse said:
I have two arrays of equal length that contain null values. I want one
array with fewer nulls. This almost works:

Do you care about the order of the elements in your resulting array? if
not, why not:

@t = grep {$_} @f, @g;

Best,
Xicheng
 
I

it_says_BALLS_on_your forehead

Samwyse said:
I have two arrays of equal length that contain null values. I want one
array with fewer nulls. This almost works:

push @t, shift(@f).shift(@g) while scalar @f;

except that every once in a while both arrays have values in the same
slot. This won't work at all:

push @t, shift(@f)||shift(@g) while scalar @f;

because the || operator short-circuits. Can anyone do this in one line,
or do I need do it the hard way:

while (scalar @f) {
($a, $b) = (shift(@f), shift(@g));
push @t, $a || $b;
}


per the Cookbook 2nd ed. p. 117, sparse arrays should be implemented by
using an hash, not an array.
 
I

it_says_BALLS_on_your forehead

it_says_BALLS_on_your forehead said:
per the Cookbook 2nd ed. p. 117, sparse arrays should be implemented by
using an hash, not an array.

s/an/a/;
 
S

Samwyse

Paul said:
Samwyse said:
I have two arrays of equal length that contain null values. I want one
array with fewer nulls.

I don't especially understand your goal, but what about...

push @t, $f[$_] || $g[$_] for 0..$#f;

A most excellent solution.
? Your description gave no requirement that @f or @g had to be
depleted by the expression...

They're both temp vars, so it doesn't matter.
You might also find one or more of List::MoreUtils's functions handy:
@t = pairwise { $a || $b } @f, @g;

I probably need to better acquaint myself with that module. Due to an
exposure to APL at a tender age, I find myself frequently wanting to
manipulate arrays in a manner that current languages rarely support.
Perl comes closer than most, and Perl 6 will be ideal.
I have to point out that your problem description is incomplete at best
- you said your first solution only "almost" works, because the two
arrays might have defined values in the same "slot"... but you never
said what you want to happen in that case.

Actually, I gave an example of code that does what I need, which
implicit defining most of the cases that you mention. If anyting, the
sample code over-specified the problem, since I did fail to mention that
the final values of the arrays were of no concern.

Thanks for the tutoring.
 
S

Samwyse

Abigail said:
Samwyse ([email protected]) wrote on MMMMDLI September MCMXCIII in
<URL:** I have two arrays of equal length that contain null values. I want one
** array with fewer nulls.

I'd avoid push, and do something like:

my @t = map {defined $f [$_] ? $f [$_] : $g [$_]} 0 .. $#f;

Or if you have the defined-or operator:

my @t = map {$f [$_] // $g [$_]} 0 .. $#f;

Note that I didn't use '$f [$_] || $g [$_]', as that will assign the
value of @g if the corresponding value of @f is 0, or the empty string
(both values are defined, but false).

In this case, the data is coming from a CSV file, so undefined values
are represented by empty strings, and zeros aren't a concern. In fact,
I was a bit surprised to find out that Text::parseWords returns undef's
for empty fields; it caused a bit of trouble when I later used join(',',
....) to write the merged arrays back to a file.

I was under the impression that defined-or was a Perl 6 feature. I
guess I need to check if my current interpreter supports it.

Thanks!
 
T

Tad McClellan

Samwyse said:
Abigail said:
Samwyse ([email protected]) wrote on MMMMDLI September MCMXCIII in
<URL:** I have two arrays of equal length that contain null values. I want one
** array with fewer nulls.

I'd avoid push, and do something like:

my @t = map {defined $f [$_] ? $f [$_] : $g [$_]} 0 .. $#f;

Or if you have the defined-or operator:

my @t = map {$f [$_] // $g [$_]} 0 .. $#f;

Note that I didn't use '$f [$_] || $g [$_]', as that will assign the
value of @g if the corresponding value of @f is 0, or the empty string
(both values are defined, but false).

In this case, the data is coming from a CSV file, so undefined values
are represented by empty strings,


Then Abigail's note would apply.

and zeros aren't a concern.


Yes they are:

"foo","0","bar"

Then Abigail's note would again apply for the 2nd field there.
 
S

Samwyse

Tad said:
Then Abigail's note would apply.


Yes they are:

"foo","0","bar"

Then Abigail's note would again apply for the 2nd field there.

Sorry, I meant to say that zeros aren't a concern for my particular
dataset, as none of the fields contain numeric data, zero (even quoted)
is not a valid value, and I've previously verified the validity of the
data that is present.
 
R

robic0

Samwyse ([email protected]) wrote on MMMMDLII September MCMXCIII in
<URL:^^ Abigail wrote:
^^ > Samwyse ([email protected]) wrote on MMMMDLI September MCMXCIII in
^^ > <URL:^^ > ** I have two arrays of equal length that contain null values. I want one
^^ > ** array with fewer nulls.
^^ >
^^ > I'd avoid push, and do something like:
^^ >
^^ > my @t = map {defined $f [$_] ? $f [$_] : $g [$_]} 0 .. $#f;
^^ >
^^ > Or if you have the defined-or operator:
^^ >
^^ > my @t = map {$f [$_] // $g [$_]} 0 .. $#f;
^^ >
^^ > Note that I didn't use '$f [$_] || $g [$_]', as that will assign the
^^ > value of @g if the corresponding value of @f is 0, or the empty string
^^ > (both values are defined, but false).
^^
^^ In this case, the data is coming from a CSV file, so undefined values
^^ are represented by empty strings, and zeros aren't a concern. In fact,
^^ I was a bit surprised to find out that Text::parseWords returns undef's
^^ for empty fields; it caused a bit of trouble when I later used join(',',
^^ ...) to write the merged arrays back to a file.
^^
^^ I was under the impression that defined-or was a Perl 6 feature. I
^^ guess I need to check if my current interpreter supports it.


Defined-or will be in 5.10, is currently in 5.9.3, and there's a patch
available for 5.8.x.

I would like to understand your post but I can't. Can you explain your
'^^ >' syntax so I can try to percieve what it is that has been quoted.
Also, could you explain your bizzaro sig regex's as the change so that
someone might not think you have a fuckin "screw loose" ????
Thanks big gurl...
(the line just above will evolve just like your sig regex if you don't respond)
 
R

robic0

Samwyse ([email protected]) wrote on MMMMDLII September MCMXCIII in
<URL:^^ Abigail wrote: snipper
Defined-or will be in 5.10, is currently in 5.9.3, and there's a patch
available for 5.8.x.
Patches, defined in 5.10, 5.9.3, available for 5.8.x<--wtf is that?
Alot of corporations use 5.8.x<--, can we be assured you know what
your talking about Abby? As far as i see your blowing sunshine up
alot of buts here.

Explain in detail what your talking about for the implementors......
 

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,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top