8 Replies Latest reply on Jul 15, 2011 1:02 PM by Adam Cameron.

    Merging Arrays


      I have 4 Arrays of Objects/Structures in my function that I need to merge into one Array so I can return it to my Flex app. I googled it and found a bunch of articles that talk about using the Java function addAll(), but when I tried, it returned an errors saying the function was not found. I saw other articles that talked about the old way of looping over with the Array attribute and passing in the index, but I keep getting a weird Java Boolean as an Array error. Can anyone help me figure this out?


      Here is what I have:


      <cfset allPets = ArrayNew(1) />
              <cfloop array="#adoptables#" index="i">
                    <cfset allPets = ArrayAppend(allPets, #i#)>
              <cfloop array="#pending#" index="i">
                    <cfset allPets = ArrayAppend(allPets, #i#)>
              <cfloop array="#adopted#" index="i">
                    <cfset allPets =  ArrayAppend(allPets, #i#)>
              <cfloop array="#hold#" index="i">
                    <cfset allPets =  ArrayAppend(allPets, #i#)>


      It is an Array of Structures if that helps. Thanks!

        • 1. Re: Merging Arrays
          Adam Cameron. Level 5

          Read the docs.


          http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7f 21.html


          What does arrayAppend() return?


          How does the docs say arrayAppend() should be used?




          • 2. Re: Merging Arrays
            ilssac Level 5

            And once you have learned what Adam is showing you don't feel to bad.


            I'm ALWAYS confusing the behaviors of ArrayAppend() and ListAppend() [and the prepend versions] and mistyping which one needs to reset the variable and which one does not.

            • 3. Re: Merging Arrays
              insuractive Level 3

              You could always use ArrayToList() to flatten your arrays, concatenate them together into one long list and then combine using ListToArray().  You may need to use a custom delimeter (e.g. |) if you think your array values might have commas.  It essentially accomplishes that same thing, but requires less lines of code and might be a little cleaner to maintain.


              Of course it helps if I actually read the original post a little better.  Doh - arrays of structures.  Yeah - those don't flatten too well.  You could always accomplish the same thing with serializing/deserializing the data using WDDX or JSON.


              Message was edited by: insuractive

              • 4. Re: Merging Arrays
                Adam Cameron. Level 5

                This has come back onto my radar due to inursactive's reply.


                On re-read, I spotted this:

                I googled it and found a bunch of articles that talk about using the Java function addAll(), but when I tried, it returned an errors saying the function was not found


                This didn't ring true to me, because I've used addAll() to concatenate CF arrays ebfore, so I looked into it.


                This code works fine:


                    a1 = [];
                    a2 = [];
                    for (i=1; i <=5; i++){
                        a1[i] = {
                            number = i
                        a2[i] = {
                            letter = chr(64+i)


                So I'm interested to see what your code was...




                • 5. Re: Merging Arrays
                  insuractive Level 3

                  Wow, that's pretty slick.  I always forget about the underlying Java classes behind the CF objects.  In case you're not familiar with this technique wmkolcz - remember that anytime you use an "undocumented" feature in CF there is a chance (though very small in this case) that an update to CF will break your functionality - say if the CF team decides to rewrite the underlying class behind the array object in CF.  Ben Nadel has an excellent article where he looks at this exact issue and builds an array append/combine custom function in CF along with an excellent discussion in the comments about the various pros/cons of the different methods:


                  http://www.bennadel.com/blog/2059-Appending-One-Array-To-Another-With-ArrayAppendAll-In-Co ldFusion.htm


                  IMHO - Adam's solution will be the quickest and most reliable of all the suggestions.  I just thought you might not be aware of the implications.

                  • 6. Re: Merging Arrays
                    -==cfSearching==- Level 4
                    discussion in the comments about the various pros/cons of the different methods:


                    Two other considerations you do not hear discussed much (though you should):

                    anytime you use an "undocumented" feature ... there is a chance .. that an update to CF will break your functionalityaware of the implications.


                    1) It is a risk. Some things are obviously more risky than others. ie ServiceFactory is more risky than using a java.lang.String. However, if you do chose to use this stuff, try and stick to using interfaces. Those are less likely to change than the underlying implementation. For example with CF arrays, do not use methods found only in  java.util.Vector such as elementAt(..). Stick the methods in java.util.List and you will better insulate yourself against changes.  Then if adobe  decides arrays should be implemented as java.util.ArrayList tomorrow,  your code will still work. At least under ACF anyway. As mentioned in the  link, you basically throw portability out the window once you start  using the java internals. So if you are even thinking about using multiple engines, it is an important consideration.


                    2)  A lot of java classes have nuances CF lacks. Be sure to know the classes you are using and how they differ from CF.  It is extremely easy to trip yourself up by overlooking those small differences.


                       // resulting array might not be what you expect ...
                        jArr = str.split("|");
                       // jArr is not a CF array. so the append fails
                        arrayAppend(jArr, "grape");


                       // parameter test is not found because map is case sensitive
                       // url: test.cfm?tesT=123
                       map = getPageContext().getRequest().getParameterMap();
                       structKeyExists(map, "test");

                    • 7. Re: Merging Arrays
                      insuractive Level 3

                      well said.

                      • 8. Re: Merging Arrays
                        Adam Cameron. Level 5

                        1) It is a risk.


                        It is.  But one has to be realistic about the degree of the risk.  I think as long as one is mindful of the situation, then it's a better approach to code the best solution for here and now, rather than defensively code for some remote possibility of compatibility issues down the track.


                        If one has well-designed code and good test coverage, identifying compat issues is easy, and they're also easy to deal with.


                        You also mention portability... in my experience I've got observations here:

                        * you'll have as many problems with native CF tags and functions and datatypes as you will with this sort of thing, when porting to one of the "cheaper" (in more than one senses of that term) CF application servers;

                        * what percentage of CF code ever gets ported anyhow?  I've written an app that needs to run on CF, OpenBD, BD.NET and Railo, but only once.  The rest of it is born, lives and eventually dies on one of those platforms.  Obviously I am not a statistically sound sample though ;-)


                        Now I'm not trying to suggest I don't agree with everything you say - I do agree with it - but I dunno how important a consideration it is.  Beyond being aware of it.