Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using structKeyExists for nested objects

I have a nested struct like so struct1.struct2.foo. I would like to check if foo exists. However, struct2 isn't guaranteed to exists either. I loathe to use isDefined(), but I also think that calling structKeyExists() twice is wasteful (e.g., if (structKeyExists(struct, 'struct2') && structKeyExists(struct.struct2, 'foo')) {}

I thought about using structFindKey(), but then I don't want to run into an issue if there exists struct1.foo

Is there a better way to accomplish this?

This is a similar question to this question, but I am not dealing with an XML document so most of the answers in that post doesn't work for me.

like image 364
RHPT Avatar asked Dec 27 '22 09:12

RHPT


2 Answers

This is the same question (though more succinctly put) that lies at the heart of an earlier question:

How to dynamically loop through an array of structures

I would offer the same answer.

How to dynamically loop through an array of structures

To repeat the essential part, the following function should do what you want:

 <cffunction name="StructGetByKeyList">
      <cfargument name="struct">
      <cfargument name="key">

      <cfif StructKeyExists(struct,ListFirst(key,"."))>
           <cfif ListLen(key,".") GT 1>
                <cfreturn StructGetByKeyList(struct[ListFirst(key,".")],ListRest(key,"."))>
           <cfelse>
                <cfreturn struct[key]>
           </cfif>
      <cfelse>
           <cfreturn "">
      </cfif>
 </cffunction>

Then you could just call StructGetByKeyList(struct1,"struct2.foo") and it would return the string for the key if it exists and an empty string if it does not.

To return a boolean instead, use the following:

<cffunction name="StructNestedKeyExists">
    <cfargument name="struct">
    <cfargument name="key">

    <cfif StructKeyExists(struct,ListFirst(key,"."))>
        <cfif ListLen(key,".") GT 1>
            <cfreturn StructNestedKeyExists(struct[ListFirst(key,".")],ListRest(key,"."))>
        <cfelse>
            <cfreturn true>
        </cfif>
    <cfelse>
        <cfreturn false>
    </cfif>
</cffunction>
like image 130
Steve Bryant Avatar answered Jan 08 '23 01:01

Steve Bryant


Nothing wrong with using isDefined("struct1.struct2.foo"). It's not as awfully slow as you think. Start with a scope, if you want to make it a bit faster, like "variables.struct1.struct2.foo"

ColdFusion 9 CFML Reference (PDF)

like image 44
Henry Avatar answered Jan 08 '23 01:01

Henry