2

I have array of structures where I should access specific field. Here is example of my data:

array
1   
   struct
   address_city     Washington
   address_state    DC
array
2   
   struct
   address_city     New York
   address_state    NY
array
3   
   struct
   address_city     Miami
   address_state    FL

I have this code to loop over array and then inner loop to iterate over structures:

<cfloop from="1" to="#arrayLen(arrData)#" index="i">
    <cfset data = arrData[i]>
    <cfloop collection="#data#" item="key">
        <cfoutput>#key#:#data[key]#<br></cfoutput>
    </cfloop> 
</cfloop>

Code above will produce this output:

address_city:Washington
address_state:DC
address_city:New York
address_state:NY
address_city:Miami
address_state:FL

Instead I need to access only address_state value. I have tried something like this:

<cfloop from="1" to="#arrayLen(arrData)#" index="i">
    <cfset data = arrData[i]>
    <cfloop collection="#data#" item="key">
        <cfoutput>#data[key]['address_state']#<br></cfoutput>
    </cfloop> 
</cfloop>

Then I was getting this error message:

Message     You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members. 

Is there a way to output only one field from each structure in array? Something similar is doable in JavaScript when iterating over JS Object. Example:

for (var key in data) {
    console.log(data[key]['address_state']);
}

If anyone knows the way to achieve this in ColdFusion please let me know.

espresso_coffee
  • 5,980
  • 11
  • 83
  • 193

2 Answers2

3

Funny enough, there is a way to do it almost exactly like the JS example.

for (key in data) {
    writeOutput( "Address State = " & key.address_state & "<br>");
}

https://trycf.com/gist/f0bd28bbf644912d320b10fdc5f526f4/acf?theme=monokai

You were getting the error because you were referencing the data array when you didn't need to. You were already looping through the keys in data by nature of your loop. In your script example, you didn't need to do a double loop through your array.

Shawn
  • 4,758
  • 1
  • 20
  • 29
  • I use `ColdFusion 10` not sure that is supported. At least when I tried I got the same error that I mentioned above. – espresso_coffee Dec 04 '18 at 18:40
  • Adobe CF10? That TryCF.com link is in ColdFusion 10. It should work. Did you try the exact code sample I included? It shouldn't give you an error like that. – Shawn Dec 04 '18 at 18:42
  • @espresso_coffee Can you use TryCF to create your data structure? Is it a single array that holds structs of data? Or is it an array that holds other arrays that hold struct data? – Shawn Dec 04 '18 at 18:44
  • IT WORKS! Funny enough only when I use `cfscript`, If I try to do that with `cfml` then I get the error. – espresso_coffee Dec 04 '18 at 18:46
  • You just have to make sure you are referencing the correct part of your object. If you get errors about not being able to convert complex objects to simple objects, then dump the variable to see what you're working with. – Shawn Dec 04 '18 at 18:54
  • And as a personal note: I find it significantly easier to loop in cfscript (among other things). I do realize that CF10 is more limited with cfscript than more recent versions, but it still includes almost everything you'd need to do. – Shawn Dec 04 '18 at 18:58
  • So since you mentioned that I have a question now. I'm currently limited and I have to use CF 10. SO far I was able to convert any code to cfscript except the case where I have to loop over data and use `cfquery` to insert/update data. Do you have a good example on how to achieve that? Thank you. – espresso_coffee Dec 04 '18 at 19:04
  • 1
    @espresso_coffee You shouldn't loop over a query. That will cause a lot of unnecessary network activity, and reconnecting each loop will cause a significant amount of latency. You'd be better to write a query that can get multiple results or perform multiple inserts in one call. What database are you using? – Shawn Dec 04 '18 at 19:12
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184714/discussion-between-espresso-coffee-and-shawn). – espresso_coffee Dec 04 '18 at 19:18
  • @expresso_coffee "You shouldn't loop over a query. That will cause a lot of unnecessary network activity," Just for the record this DOES NOT cause any futher network activity. The query is iterated over in a query 'object' in memory. #sigh – Dawesi Mar 20 '23 at 22:59
2

I've go through your issue and I hope you got a answer based on script based coding style. But As you said in above comments you need functionality based on tag. So here I've post my functionality based on tag. I hope it's will help you. Thanks.

<cfloop array ="#arrData#" index="data">
    Address_State: #data.address_state# <br>
</cfloop>
AishuSuhan P
  • 123
  • 5
  • Just a note, but I don't see where OP said he had to use tags. Regardless, even though it's CF10, I'd still recommending using script anywhere that it's possible (which is close to everything in 10). I think the tagginess of CF is one of the reasons it gets bashed (though it also can make it easy to learn/use). But pointing out that an array loop is much more appropriate is a big key here. – Shawn Dec 05 '18 at 14:28
  • Agree, this is THE correct answer to the question. – Dawesi Mar 20 '23 at 23:00