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!sid
ziegast@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