У меня есть массив структур в ColdFusion. Я хотел бы отсортировать этот массив на основе одного из атрибутов в структурах. Как я могу достигнуть этого? Я нашел функцию StructSort, но она берет структуру, и у меня есть массив.
Если это не возможно просто в ColdFusion, это возможный в Java так или иначе (возможно, использование Arrays.sort(Object[], Comparator)
)?
Как обычно, на 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;
}
Если вы не хотите использовать собственные методы, в Coldfusion есть structSort метод http://www.cfquickdocs.com/cf8/#StructSort . Да, он сортирует структуру с вложенными структурами, НО возвращает массив, поэтому его можно использовать для достижения того же результата.
Вот что-то, что очень похоже на исходный 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>
Результат:
Принятое решение (из 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');
Итерация по отсортированному массиву и печать названия и веса. Это не будет в правильном порядке, и это ограничение смешивания произвольного ключа с сортируемым значением.