sid@think.com (Sid Stuart) (05/30/91)
I am writing a Perl application in which I would like to store
into an associative array only if an entry for that key does
not exist. The problem is I may come up with duplicate keys and
I don't want to overwrite the contents of an entry. Is there a
cheap way to find out if a key is in use? By cheap I mean other
than using the functions "keys" or "each" to search through all
the keys of the array.
Thanks for the time,
Sid Stuart
sid@think.com
--
Sid Stuart, Thinking Machines Corp.
sid@think.com
{uunet,harvard}!think!sidziegast@eng.umd.edu (Eric W. Ziegast) (05/31/91)
In article <1991May30.134223.23225@Think.COM> sid@think.com (Sid Stuart) writes: > >I am writing a Perl application in which I would like to store >into an associative array only if an entry for that key does >not exist. The problem is I may come up with duplicate keys and >I don't want to overwrite the contents of an entry. Is there a >cheap way to find out if a key is in use? By cheap I mean other >than using the functions "keys" or "each" to search through all >the keys of the array. print defined($assoc{$key}) ? "$assoc{$key}\n" : "Key $key undefined\n"; So long as you don't set $assoc{$key} to a value (even ""), that entry in the associative should be undefined. Eric Z. -- +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Eric W. Ziegast Internet: ziegast@eng.umd.edu | | Univ. of Merryland Phonenet: Eric@[301.405.3689] | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
Tom Christiansen <tchrist@convex.COM> (05/31/91)
From the keyboard of sid@think.com (Sid Stuart):
:
:I am writing a Perl application in which I would like to store
:into an associative array only if an entry for that key does
:not exist. The problem is I may come up with duplicate keys and
:I don't want to overwrite the contents of an entry. Is there a
:cheap way to find out if a key is in use? By cheap I mean other
:than using the functions "keys" or "each" to search through all
:the keys of the array.
Barring pathological cases (keys whose values are undef), you
could do this:
$ary{$key} = $val unless defined $ary{$key};
or perhaps
$ary{$key} .= $val . ' ';
--tom
--
Tom Christiansen tchrist@convex.com convex!tchrist
"So much mail, so little time." przemek@rrdstrad.nist.gov (Przemek Klosowski) (05/31/91)
Hello! The solution to a problem with testing if associative array element was already defined reminded me of a problem I had, and couldn't figure out. How does one check if the associative array was assigned at all? My program runs a loop initializing an array, but each individual initialization is conditioned on something. On a rainy day all conditions could be false: is there a way to find out? The obvious $#ary doesn't work, since it refers to @ary. defined(%ary) is no good, since %ary might be pre-defined in a local(). Ideas, anyone? przemek -- przemek klosowski (przemek@ndcvx.cc.nd.edu) Physics Department University of Notre Dame IN 46556
tchrist@convex.COM (Tom Christiansen) (05/31/91)
From the keyboard of przemek@rrdstrad.nist.gov (Przemek Klosowski):
:Hello!
:The solution to a problem with testing if associative array element
:was already defined reminded me of a problem I had, and couldn't figure
:out. How does one check if the associative array was assigned at all?
:My program runs a loop initializing an array, but each individual
:initialization is conditioned on something. On a rainy day all conditions
:could be false: is there a way to find out? The obvious $#ary doesn't work,
:since it refers to @ary. defined(%ary) is no good, since %ary might be
:pre-defined in a local(). Ideas, anyone?
if (%a) {
will actually work, but I don't think that Larry has ever documented
this. More portably, and more slowly would be
if (@my_keys = keys %a) {
--tom
--
Tom Christiansen tchrist@convex.com convex!tchrist
"So much mail, so little time." ziegast@eng.umd.edu (Eric W. Ziegast) (05/31/91)
(Tom Christiansen) writes: > From the keyboard of (Przemek Klosowski): > How does one check if the associative array was assigned at all? > :My program runs a loop initializing an array, but each individual > :initialization is conditioned on something. On a rainy day all conditions > :could be false: is there a way to find out? The obvious $#ary doesn't work, > :since it refers to @ary. defined(%ary) is no good, since %ary might be > :pre-defined in a local(). Ideas, anyone? > > if (%a) { > > will actually work, but I don't think that Larry has ever documented > this. More portably, and more slowly would be > > if (@my_keys = keys %a) { Perhaps this should be documented. I gave it a few tests of wort-case scenarios... 1. Null assignment (an assignment nonetheless) $assoc{''}=''; print %assoc ? "true" : "false"; Results in true. 2. Defining the assoc as a local sub foo { local(%assoc); print %assoc ? "true" : "false"; } &foo Results in false. 3. A new dbm file dbmopen(%assoc,"newdbmfile",0600); print %assoc ? "true" : "false"; Results in false. I performed these tests with Perl 3.0 (41) on a SunOS 4.1 system. I believe ndbm was compiled into our perl. Just FYI. Someone more knowledgable might want to explain why/how this works. -- Eric Ziegast
tchrist@convex.COM (Tom Christiansen) (05/31/91)
From the keyboard of ziegast@eng.umd.edu (Eric W. Ziegast): :(Tom Christiansen) writes: :> From the keyboard of (Przemek Klosowski): :> How does one check if the associative array was assigned at all? :> :> if (%a) { :> :> will actually work, but I don't think that Larry has ever documented :> this. :Perhaps this should be documented. I gave it a few tests of wort-case :scenarios... : :Someone more knowledgable might want to explain why/how this works. Here's an article from Larry around 3700 articles ago explaining this: Date: 30 Jul 90 18:24:01 GMT From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Subject: Re: #elements in assoc array / array in scalar context Reply-to: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Propulsion Laboratory, Pasadena, CA Newsgroups: comp.lang.perl In article <15429@thorin.cs.unc.edu> tell@oscar.cs.unc.edu () writes: : : What is the recommended way to find out how many elements are in an : associative array? I don't see any method that looks particularly : efficient. There isn't any efficient way. You can find out how many buckets in the hash table are in use, which will give you an approximation for non-dbm files, since most filled buckets will only have a single entry. I suppose I could keep a count, but I don't. And such a count wouldn't work on dbm files anyway. Currently, in a scalar context, %array returns the filled_buckets/allocated_buckets ratio. That's 0/4 on an empty associative array. After the next patch, it will return 0 if no buckets are filled, so you can at least use %array as a boolean. Given the problem with dbm files, I don't anticipate changing Perl to keep track. If you want the count, then $count++. Larry Sounds like he's documented it to me. :-) --tom -- Tom Christiansen tchrist@convex.com convex!tchrist "So much mail, so little time."
lawrence@APS.Atex.Kodak.COM (Scott Lawrence) (05/31/91)
In article <1991May31.011755.4305@eng.umd.edu> ziegast@eng.umd.edu (Eric W. Ziegast) writes: Eric> I gave it a few tests of wort-case scenarios... Eric> 1. Null assignment (an assignment nonetheless) Eric> $assoc{''}=''; Eric> print %assoc ? "true" : "false"; Eric> Results in true. Eric> 2. Defining the assoc as a local Eric> sub foo { Eric> local(%assoc); Eric> print %assoc ? "true" : "false"; Eric> } Eric> &foo Eric> Results in false. Eric> 3. A new dbm file Eric> dbmopen(%assoc,"newdbmfile",0600); Eric> print %assoc ? "true" : "false"; Eric> Results in false. Eric> I performed these tests with Perl 3.0 (41) on a SunOS 4.1 system. Eric> I believe ndbm was compiled into our perl. Just FYI. Eric> Eric Ziegast I got the same results with 4.03 on SunOS 4.1, and was prompted to check on the behaviour of `defined' in those same cases. The interesting one turned out to be case 2, in which local( %assoc2 ) does not cause defined( %assoc2 ) to return true. =========== $assoc1{''}=''; print "Case 1 ", ( defined( %assoc1 )? "defined" : "undefined" ), "\n"; Case 1 defined <<<<<< makes sense ====== sub case2 { local( %assoc2 ); print "Case 2 ", (defined(%assoc2)? "defined" : "undefined" ), "\n"; } &case2; Case 2 undefined ====== dbmopen( %assoc3, "/tmp/testdbmfile", 0777); print "Case 3 ", (defined(%assoc3)? "defined" : "undefined" ), "\n"; Case 3 defined ====== -- Scott Lawrence <lawrence@APS.Atex.Kodak.COM> Voice: {US} 508-670-4023 Atex Advanced Publishing Systems G3Fax: {US} 508-670-4033 Atex, Inc; 165 Lexington St. MS 400/165L; Billerica MA 01821
allbery@NCoast.ORG (Brandon S. Allbery KF8NH) (06/04/91)
As quoted from <1991May30.205555.14490@convex.com> by Tom Christiansen <tchrist@convex.COM>: +--------------- | if (%a) { | | will actually work, but I don't think that Larry has ever documented | this. More portably, and more slowly would be +--------------- Not in so many words he hasn't, but %a has an array value, and therefore has a scalar value (the number of elements in the array generated by %a in an array context). Note that %a will be *twice* the number of entries in the assoc array, since it is a list of keys *and* values. ...but it occurs to me that %a in either context will not do what you expect if %a has been bound to a dbm file. Ooooops. ++Brandon -- Me: Brandon S. Allbery KF8NH: DC to LIGHT! [44.70.4.88] Internet: allbery@NCoast.ORG Delphi: ALLBERY uunet!usenet.ins.cwru.edu!ncoast!allbery
tchrist@convex.COM (Tom Christiansen) (06/04/91)
From the keyboard of allbery@ncoast.ORG (Brandon S. Allbery KF8NH):
:As quoted from <1991May30.205555.14490@convex.com> by Tom Christiansen <tchrist@convex.COM>:
:+---------------
:| if (%a) {
:|
:| will actually work, but I don't think that Larry has ever documented
:| this. More portably, and more slowly would be
:+---------------
:
:Not in so many words he hasn't, but %a has an array value, and therefore has a
:scalar value (the number of elements in the array generated by %a in an array
:context). Note that %a will be *twice* the number of entries in the assoc
:array, since it is a list of keys *and* values.
Um, no, I don't think that's what's afoot: see Larry's article I reposted
on what you get from a scalar %a reference.
--tom
--
Tom Christiansen tchrist@convex.com convex!tchrist
"Perl is to sed as C is to assembly language." -me