How to sort an array of structs in ColdFusion

后端 未结 10 1651
余生分开走
余生分开走 2020-12-17 10:00

I have an array of structs in ColdFusion. I\'d like to sort this array based on one of the attributes in the structs. How can I achieve this? I\'ve found the StructSort fun

相关标签:
10条回答
  • 2020-12-17 10:24

    The accepted solution (from CFLib.org) is NOT safe. I experimented with this for something I needed to do at work and found that it returns incorrect results when sorting numeric with floats.

    For example if I have these structs: (pseudocode)

    
    a = ArrayNew(1);
    
    s = StructNew();
    s.name = 'orange';
    s.weight = 200;
    ArrayAppend(a, s);
    
    s = StructNew();
    s.name = 'strawberry';
    s.weight = 28;
    ArrayAppend(a, s);
    
    s = StructNew();
    s.name = 'banana';
    s.weight = 90.55;
    ArrayAppend(a, s);
    
    sorted_array = arrayOfStructsSort(a, 'weight', 'asc', 'numeric');
    
    

    Iterate over the sorted array and print the name & weight. It won't be in the right order, and this is a limitation of mixing an arbitrary key with the value being sorted.

    0 讨论(0)
  • 2020-12-17 10:26

    Easy solution to sort an array of structures using more than one key using arraySort callback:

    It takes array of structs to be sorted as first parameter and array of structs in format of sortkey/sortorder pair as second parameter e.g. [{sortkey: 'FirstName', sortorder: 'asc'}, {sortkey: 'LastName', sortorder: 'desc'}].

    <cffunction name="arrayOfStructsSort" access="public" returntype="array" output="false" hint="This sorts an array of structures.">
        <cfargument name="aOfS" type="array" required="yes" />
        <cfargument name="key_sortOrder" type="array" required="yes" />
        <cfscript>
    
        arraySort(
            aOfS,
            function (a, b) {
                for (var i = 1; i lte arrayLen(key_sortOrder); i = i + 1) {
                    var prop = key_sortOrder[i];
                    var key = prop.key;
                    var sortOrder = prop.sortOrder;
                    if (a[key] lt b[key]) {
                        if (sortOrder eq 'desc') {
                            return 1;
                        } else {
                            return -1;
                        }
                    }
                    if (a[key] gt b[key]) {
                        if (sortOrder eq 'desc') {
                            return -1;
                        } else {
                            return 1;
                        }
                    }
                }
                return 0;
            }
        );
    
        return aOfS;
    
        </cfscript>
    
    </cffunction>
    

    Simply call it with:

    <cfset ArraySorted = arrayOfStructsSort(arrayToBeSorted,arrayOfSorkeys)>
    
    0 讨论(0)
  • 2020-12-17 10:32

    In case you don't want to use custom methods, Coldfusion has structSort method http://www.cfquickdocs.com/cf8/#StructSort . Yes it sorts structure with nested structures, BUT returns array so could be used to achieve same result.

    0 讨论(0)
  • 2020-12-17 10:33

    Here is something that closely resembles the original StructSort(). It also supports the pathToSubElement argument.

    <cffunction name="ArrayOfStructSort" returntype="array" access="public" output="no">
      <cfargument name="base" type="array" required="yes" />
      <cfargument name="sortType" type="string" required="no" default="text" />
      <cfargument name="sortOrder" type="string" required="no" default="ASC" />
      <cfargument name="pathToSubElement" type="string" required="no" default="" />
    
      <cfset var tmpStruct = StructNew()>
      <cfset var returnVal = ArrayNew(1)>
      <cfset var i = 0>
      <cfset var keys = "">
    
      <cfloop from="1" to="#ArrayLen(base)#" index="i">
        <cfset tmpStruct[i] = base[i]>
      </cfloop>
    
      <cfset keys = StructSort(tmpStruct, sortType, sortOrder, pathToSubElement)>
    
      <cfloop from="1" to="#ArrayLen(keys)#" index="i">
        <cfset returnVal[i] = tmpStruct[keys[i]]>
      </cfloop>
    
      <cfreturn returnVal>
    </cffunction>
    

    Usage / test:

    <cfscript> 
      arr = ArrayNew(1);
    
      for (i = 1; i lte 5; i = i + 1) {
        s = StructNew();
        s.a.b = 6 - i;
        ArrayAppend(arr, s);
      }
    </cfscript> 
    
    <cfset sorted = ArrayOfStructSort(arr, "numeric", "asc", "a.b")>
    
    <table><tr>
      <td><cfdump var="#arr#"></td>
      <td><cfdump var="#sorted#"></td>
    </tr></table>
    

    Result:

    ArrayOfStructSort Result

    0 讨论(0)
提交回复
热议问题