Couple of array/reference type questions

A

Arvin Portlock

There are several array type things I find myself doing all
the time and I'd like to know, once and for all, the best way
to do them. For the moment I'm most interested in core language
commands rather than specialized modules, but I'm interested to
hear about modules as well if they're really useful.

1. Grepping an array of references possible?
If I have an array of hash references, is there a way to use
grep() to find those elements whose values match a given value?
I.e., is there a grep() way to do this? I just like grep () and
I'm confortable with it and want to use it as much as I can.

my $ref = {};
$ref->{title} = 'Gone with the wind';
$ref->{date} = '1952';
push @books, $ref;
my @mybooks;
foreach my $book (@books) {
if ($book->{title} =~ /Gone/) {
push @mybooks, $book;
}
}

How would I use grep () in a scalar context if I just wanted
to know how many books contained "Gone" and didn't want to
create a new array? How about if I only wanted to know whether
the array contained ANY book whose title contained that word,
without the overhead of counting them all? For that last I'm
guessing a foreach loop is as good as it gets, but since I do
it all the time I just want to make sure I'm not missing any-
thing magical.

2. Replacing elements of an array of references.
Suppose I'm a book seller who just got in a new shipment of
"Gone with the wind." I want to replace the old edition in
my array with the new edition. This is the best I can come up
with (preserving order is important):

my $new_edition = {};
$new_edition->{title} = 'Gone with the wind';
$new_edition->{date} = '2003';
for (my $i = 0; $i++; $i <= $#books) {
$books->[$i] = $new_edition if $books->[$i]->{title}
eq 'Gone with the wind';
}

Any way to do this with grep ()?


Those are the only two I can think of at the moment. Thanks for
any advice!
 
A

Arvin Portlock

Now I remember the other one:

How do I find the last subscript of a reference to an
array without first dereferencing it? You know, with the
$# syntax.

Thank you again,
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

@agate.berkeley.edu:


1. Grepping an array of references possible? ....

my $ref = {};
$ref->{title} = 'Gone with the wind';
$ref->{date} = '1952';
push @books, $ref;
my @mybooks;
foreach my $book (@books) {
if ($book->{title} =~ /Gone/) {
push @mybooks, $book;
}
}

@mybooks = grep $_->{title} =~ /Gone/, @books;
How would I use grep () in a scalar context if I just wanted
to know how many books contained "Gone" and didn't want to
create a new array?

$num = grep $_->{title} =~ /Gone/, @books;
How about if I only wanted to know whether
the array contained ANY book whose title contained that word,

if (grep $_->{title} =~ /Gone/, @books) { ...}

But you're right, a foreach loop is not a bad way to do that, especially
if the list is large, and you use 'last' once you have found a match.
2. Replacing elements of an array of references. ....

my $new_edition = {};
$new_edition->{title} = 'Gone with the wind';
$new_edition->{date} = '2003';
for (my $i = 0; $i++; $i <= $#books) {
$books->[$i] = $new_edition if $books->[$i]->{title}
eq 'Gone with the wind';
}

Any way to do this with grep ()?

No; a foreach loop is your best bet here:

foreach my $book (@$books)
{
$book = $new_edition if $book->{title} eq '....';
}

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPxHLkmPeouIeTNHoEQIYRACeN8hFSv1+6HlLNrHju1jqd4lHO3AAoPn2
hYnPru0bZbhNYPFSlmAk8oBw
=+f9C
-----END PGP SIGNATURE-----
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I'm printing this out and pinning it to my computer! Thanks you so
much Eric.

BTW, yes, the foreach is cleaner than my for. I forgot they're
references after all and I needn't go through all that subscript
nonsense.

Just remember: An array reference is just like an array, except that you
have to go through one extra step to dereference it when you use it.

- --
Eric
$_ = reverse sort qw p ekca lre Js reh ts
p, $/.r, map $_.$", qw e p h tona e; print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBPxJ8T2PeouIeTNHoEQLy8QCeO/mpBm8N2/el4ow12FtqeqgExagAniql
qgvs3x3r8HyKpYqe/e7LTzjn
=OXbq
-----END PGP SIGNATURE-----
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top