Search code examples
coldfusioncoldfusion-9

How to dynamically loop through an array of structures


I need to create a query object out of an array of structures. The array has about 200 keys and the structures inside the array vary in name, size and depth. Here's what one node looks like:

array of structures I need to loop thru and create query object

I already have it working fine for array[#i].adGroupId and array[#i#].userStatus but I need to check if a structure value exists before adding it to the query. criterion.text for example isn't always in the structure so I need to check that, but not sure how. Here's the code so far but it always skips criterion.text and bids.maxCpc.amount.microAmount.

<cfset vColumns = "AdGroupID,KeywordText,Status,MaxCPC" />
<cfset vColumnValue = "AdGroupID,criterion.text,userStatus,bids.maxCPC" />
<cfset loopnum = 1>
<cfset myquery = QueryNew(vColumns) >
<cfloop array="#aKeywordsAll#" index="i">
    <cfset temp = QueryAddRow(myquery, 1)>
    <cfset loopNum2 = 1>
    <cfloop list="#vColumnValue#" index="j">                
        <cfif structKeyExists(aKeywordsAll[loopnum],j)>
            <cfset QuerySetCell(myquery, listGetAt(vColumns, loopNum2), aKeywordsAll[loopnum][j])>
        <cfelse>
            <cfset QuerySetCell(myquery, listGetAt(vColumns, loopNum2), "test")>
        </cfif>
        <cfset loopNum2++ />
    </cfloop>
    <cfset loopnum++ />
</cfloop>

Here's the query object created. It says "test" but hoping it would give the values:

Query object created from my crazy looping


Solution

  • Your problem is that the StructKeyExists function is looking for a key literally named "criterion.text" (for example) - which is possible, rather than a key of "text" inside of a key named "criterion". I whipped up a UDF that should solve the problem for you:

     <cffunction name="StructGetByKeyList">
        <cfargument name="struct">
        <cfargument name="key">
    
        <cfset var result = "">
    
        <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 can call Len(StructGetByKeyList(aKeywordsAll[loopnum],j)) instead of structKeyExists(aKeywordsAll[loopnum],j).

    For this line:

     <cfset QuerySetCell(myquery, listGetAt(vColumns, loopNum2), aKeywordsAll[loopnum][j])>
    

    Use this:

     <cfset QuerySetCell(myquery, listGetAt(vColumns, loopNum2), StructGetByKeyList(aKeywordsAll[loopnum],j))>