Как отсортировать массив структур в ColdFusion

У меня есть массив структур в ColdFusion. Я хотел бы отсортировать этот массив на основе одного из атрибутов в структурах. Как я могу достигнуть этого? Я нашел функцию StructSort, но она берет структуру, и у меня есть массив.

Если это не возможно просто в ColdFusion, это возможный в Java так или иначе (возможно, использование Arrays.sort(Object[], Comparator))?

19
задан Kip 16 April 2010 в 14:45
поделиться

4 ответа

Как обычно, на CFLib.org есть именно то, что вам нужно.

http://cflib.org/udf/ArrayOfStructsSort

/**
* Sorts an array of structures based on a key in the structures.
*
* @param aofS      Array of structures.
* @param key      Key to sort by.
* @param sortOrder      Order to sort by, asc or desc.
* @param sortType      Text, textnocase, or numeric.
* @param delim      Delimiter used for temporary data storage. Must not exist in data. Defaults to a period.
* @return Returns a sorted array.
* @author Nathan Dintenfass (nathan@changemedia.com)
* @version 1, December 10, 2001
*/
function arrayOfStructsSort(aOfS,key){
        //by default we'll use an ascending sort
        var sortOrder = "asc";        
        //by default, we'll use a textnocase sort
        var sortType = "textnocase";
        //by default, use ascii character 30 as the delim
        var delim = ".";
        //make an array to hold the sort stuff
        var sortArray = arraynew(1);
        //make an array to return
        var returnArray = arraynew(1);
        //grab the number of elements in the array (used in the loops)
        var count = arrayLen(aOfS);
        //make a variable to use in the loop
        var ii = 1;
        //if there is a 3rd argument, set the sortOrder
        if(arraylen(arguments) GT 2)
            sortOrder = arguments[3];
        //if there is a 4th argument, set the sortType
        if(arraylen(arguments) GT 3)
            sortType = arguments[4];
        //if there is a 5th argument, set the delim
        if(arraylen(arguments) GT 4)
            delim = arguments[5];
        //loop over the array of structs, building the sortArray
        for(ii = 1; ii lte count; ii = ii + 1)
            sortArray[ii] = aOfS[ii][key] & delim & ii;
        //now sort the array
        arraySort(sortArray,sortType,sortOrder);
        //now build the return array
        for(ii = 1; ii lte count; ii = ii + 1)
            returnArray[ii] = aOfS[listLast(sortArray[ii],delim)];
        //return the array
        return returnArray;
}
12
ответ дан 30 November 2019 в 02:48
поделиться

Если вы не хотите использовать собственные методы, в Coldfusion есть structSort метод http://www.cfquickdocs.com/cf8/#StructSort . Да, он сортирует структуру с вложенными структурами, НО возвращает массив, поэтому его можно использовать для достижения того же результата.

1
ответ дан 30 November 2019 в 02:48
поделиться

Вот что-то, что очень похоже на исходный StructSort () . Он также поддерживает аргумент pathToSubElement .

<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>

Использование / проверка:

<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>

Результат:

ArrayOfStructSort Result

16
ответ дан 30 November 2019 в 02:48
поделиться

Принятое решение (из CFLib.org) НЕ безопасно. Я экспериментировал с ним для чего-то, что мне нужно было сделать на работе, и обнаружил, что оно возвращает неверные результаты при сортировке числовых значений с плавающей точкой.

Например, если у меня есть такие структуры: (псевдокод)


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');

Итерация по отсортированному массиву и печать названия и веса. Это не будет в правильном порядке, и это ограничение смешивания произвольного ключа с сортируемым значением.

5
ответ дан 30 November 2019 в 02:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: