Skip to main content
Known Participant
February 13, 2009
Question

ColdFusion Structure

  • February 13, 2009
  • 10 replies
  • 5300 views
I'm looping an array of records (from a fixed length feed) and creating a structure for each required field. Then for every loop, I'm passing this structure to a function to check if certain required field in the structure's element is left empty.
The structure should look something like this:
<cfloop from="1" to="#ArrayLen(MyFile)#" index="i">
<cfset aEachLine =StructNew()>
<cfset aEachLine
["LastName"]="#Mid(MyFile ,17,40)#">
<cfset aEachLine
["FirstName"]="#Mid(MyFile ,57,20)#">
<cfset aEachLine
["Address"]="#Mid(MyFile ,140,38)#">
<cfset aEachLine
["City"]="#Mid(MyFile ,254,19)#">
<cfset aEachLine
["State"]="#Mid(MyFile ,273,2)#">
<cfset aEachLine
["Country"]="#Mid(MyFile ,284,4)#">

In this example I'm assuming that my structure is this short

<CFSET CheckStructValue=CheckThisStruc(aEachLine)>
</cfloop>

How do I check if any of those struct. value is empty?
This topic has been closed for replies.

10 replies

BKBK
Community Expert
Community Expert
February 18, 2009
Alecken wrote:
I don't know if this is a good approach or not but so far get me what I need.

If it gets you what you need, then it is a good approach. Good luck.

BKBK
Community Expert
Community Expert
February 16, 2009
Alecken wrote:
Now that I got all the empty elements from this structure how do I refer to each key that has empty values so I can use cfif cfelse?

In the code I gave above, the line <cfdump var="#arrayCheck#"> gives you a clue. Where Coldfusion matches an empty string, it creates an array of structs with keys 'owner' and 'key'. Use the 'key' key to get the keys that correspond to an empty string, thus

<cfif arrayLen(arrayCheck) GE 1>
<cfset emptyValuedKey = arrayCheck[1]['key']>
<p>empty-valued key: <cfoutput>#emptyValuedKey#</cfoutput></p>
</cfif>

aleckenAuthor
Known Participant
February 17, 2009
I followed your suggestion and it is working great when there is only 1 empty field.
When the array has more than 1 empty fields this code only shows one of them even with the "all" attribute from StructFindValu():
<cfif arrayLen(arrayCheck) GE 1>
<cfset emptyValuedKey = arrayCheck[1]['key']>
<p>empty-valued key: <cfoutput>#emptyValuedKey#</cfoutput></p>
</cfif>

This is what I did to get exactly those empty fields:
First: <CFSET Result=StructFindValue(stEachLine,"")>
Then:
<CFSET GetTheStruct=Result[1]>
Then:
<CFSET GetTheCoreStruct=#GetTheStruct["owner"]#>
Then:
<cfloop collection="#GetTheCoreStruct#" item="KEY">
<cfif #Trim(GetTheCoreStruct[KEY])# EQ "">
<!--- do more things here --->
</cfif>
</cfloop>

I don't know if this is a good approach or not but so far get me what I need.


Inspiring
February 16, 2009
Sorry about that. I should have noted that you need to add a third parameter to the function (StructFindValue) to get them all.

Try this code and you'll see how it differs:
<cfscript>
myStruct = StructNew();
myStruct.key1 = "";
myStruct.key2 = "Key 2 Value";
myStruct.key3 = "";

myFind = StructFindValue(myStruct,"","all");
</cfscript>
<cfdump var="#myFind#">

I still prefer looping over the struct, checking each key and value as I loop but by adding the third parameter "all" to the StructFindValue function will, at least, get you an array of all matching values.
aleckenAuthor
Known Participant
February 16, 2009
Oh I see, so that's what "all" and "One" attributes are for.
Now that I got all the empty elements from this structure how do I refer to each key that has empty values so I can use cfif cfelse?
I tried to use the cfloop collection you wrote last week, I got error saying myStruct[key]) is not a simple value so I can't use it this way

<cfloop collection="#myStruct#" item="key">
<cfif Trim(myStruct[key]) eq "">
<!--- do what you gotta here, because the key is empty --->
</cfif>
</cfloop>

Inspiring
February 16, 2009
alecken,

I don't think looping is the only way but suggested this approach because, I think, you can more easily write code that determines which key in a struct is empty (if any) and then report back to the user the issue (or do something else such as inserting default values, etc.).

That said, since the purpose of StructFindValue is to locate any key that has the value supplied, it should work. I just wrote and tested the following code and it worked:
<cfscript>
myStruct = StructNew();
myStruct.key1 = "Key 1 Value";
myStruct.key2 = "Key 2 Value";
myStruct.key3 = "";

myFind = StructFindValue(myStruct,"");
</cfscript>
<cfdump var="#myFind#">

The resulting output of an array of structures showed me that key 3 was empty.

While this works to locate empty keys, I would still need to write code that determines which key was empty and then what to do from there. I just find it easier to loop over the struct and act accordingly on each key it finds that is empty as it loops over the struct. But that's just me!

There are some structure functions on cflib.org that might help but in a cursory look over the site, I did not see anything off hand.
aleckenAuthor
Known Participant
February 16, 2009
craigkaminsky,
Thank you for helping. It failed to locate the key with empty value when I tried your suggestion using StructFindValue() but when I applied trim() on the value it is working.
<CFSET myStruct[key2] = "#Trim(Key_2_ Value#)">

One problem I'm facing right now is when there are more than 1 empty values in the structure, StructFindValue() only point to one of them.
Using your example,
If key 1 is empty, StrucFindValue() showed me only Key1 as the one with empty value BUT
if key1 and 3 are empty, StrucFindValue() showed me only Key3 as the one with empty value and this is causing problem since the business rule that I have to apply is not the same when for each scenario
Inspiring
February 16, 2009
> There's no way of checking the whole struct in one hit; you've gotta check
> each key.

>
> StructFindValue is one way. It can check the whole struct for a match to a
> string value.

Ah yes, good thinking!

--
Adam
BKBK
Community Expert
Community Expert
February 16, 2009
Adam Cameron wrote:
There's no way of checking the whole struct in one hit; you've gotta check each key.

StructFindValue is one way. It can check the whole struct for a match to a string value.

Inspiring
February 15, 2009
> How do I check if any of those struct. value is empty?

Testing the length of each key's value? There's no way of checking the
whole struct in one hit; you've gotta check each key.

--
Adam
February 14, 2009
In your code here you are creating a new structure every itieration.

quote:


<cfloop from="1" to="#ArrayLen(MyFile)#" index="i">
<cfset aEachLine
=StructNew()>
<cfset aEachLine ["LastName"]="#Mid(MyFile,17,40)#">
<cfset aEachLine ["FirstName"]="#Mid(MyFile,57,20)#">
<cfset aEachLine ["Address"]="#Mid(MyFile,140,38)#">
<cfset aEachLine ["City"]="#Mid(MyFile,254,19)#">
<cfset aEachLine ["State"]="#Mid(MyFile,273,2)#">
<cfset aEachLine ["Country"]="#Mid(MyFile,284,4)#">

In this example I'm assuming that my structure is this short

<CFSET CheckStructValue=CheckThisStruc(aEachLine)>
</cfloop>



BKBK is saying this is inefficient. It is because for each new structure, coldfusion is using memory and processing power. Rather do this.


February 14, 2009
Is this code even working? You use the Mid() function on an array in each iteration of the loop. Did you just post code that is incomplete?

For example where you have
BKBK
Community Expert
Community Expert
February 14, 2009
Alecken wrote:
As far as the logic, I'm looping from a fixed length text file. First I created an Array using the <cfset MyFile = listtoarray(MyFile,"#chr(13)##chr(10)#")>
This give me and array of fixed length records, then I loop over this array creating a structure for each required record and then checking each element of the structure if they are empty.


OK. I think there is a misunderstanding. It has to do with the fact that this forum uses [ i ] for italics. The indices i that you used in MyFile[ i ] have therefore disappeared from the right-hand side of the statements, leaving only MyFile in each case.

However, the point about moving <cfset aEachLine =StructNew()> outside the loop stays. Otherwise, you will be creating a new object with each pass of the loop, for nothing.

An alternative is to leave the line where it is. But then, modify it by giving the struct an extra key (the index). That's what I've done below.


Inspiring
February 13, 2009
To simply check the value of each key in a struct, use a collection loop.

The syntax is:
<cfloop collection="#myStruct#" item="key">
<cfif Trim(myStruct[key]) eq "">
<!--- do what you gotta here, because the key is empty --->
</cfif>
</cfloop>

You can also get the name of the key in the above loop by outputting or checking the value of the item (key).
<cfoutput>#key#</cfoutput>
Or
<cfif key eq "country">
<!--- blah blah --->
</cfif>
BKBK
Community Expert
Community Expert
February 13, 2009
How do I check if any of those struct. value is empty?
StructCount(myStructure) gives the number of keys in myStructure. It will return 0 if myStructure has no keys.

However, there's something wrong with the logic. The loop keeps creating a new structure -- a waste -- and never uses the index -- a sign of inefficiency.

aleckenAuthor
Known Participant
February 13, 2009
StructCount(myStrcuture) doesn't check for an empty value isn't it?
If in that structure, key Country doesn't have value or the value is an empty string how can I catch that, I think that is what I'm after.

As far as the logic, I'm looping from a fixed length text file. First I created an Array using the <cfset MyFile = listtoarray(MyFile,"#chr(13)##chr(10)#")>
This give me and array of fixed length records, then I loop over this array creating a structure for each required record and then checking each element of the structure if they are empty. The difficulty I'm facing is how to check
the VALUE (not the KEY) of the structure element on every loop for an empty value.