0

Here is a data dump of what I am trying to sort

array
1   
     struct
         col           1
         dataid       48
         identifier    1
         row           1
         size_x        4
         size_y        1
2   
     struct
         col           1
         dataid       42
         identifier    2
         row           2
         size_x        2
         size_y        1
3   
     struct
         col           3
         dataid       45
         identifier    3
         row           2
         size_x        2
         size_y        1

I want to sort by row first, then col. Lots of examples how to sort by one data element, but none that talk about secondary elements.

Leigh
  • 28,765
  • 10
  • 55
  • 103
user1322114
  • 317
  • 2
  • 10
  • 3
    From where did you get that array in the first place? – Dan Bracuk Nov 05 '13 at 20:32
  • 3
    [Here](http://stackoverflow.com/a/13018601/21727) is one solution. – mbeckish Nov 05 '13 at 20:44
  • You could also write your own [QuickSort](http://en.wikipedia.org/wiki/Quicksort) function and implement your own comparator function that uses both row and col to determine which element is greater. – mbeckish Nov 05 '13 at 20:46
  • What version of ColdFusion? (oks update the tagging on the question) – Adam Cameron Nov 05 '13 at 20:49
  • V10, I go this array from gridster.js (added extra elements). – user1322114 Nov 05 '13 at 21:21
  • mbeckish link he recommended worked flawlessly, had it implemented within minutes. Thanks man – user1322114 Nov 05 '13 at 21:39
  • None of the answers there are optimal for CF10. See my answer for a CF10 (or Railo) approach. – Adam Cameron Nov 05 '13 at 21:58
  • Actually [one of the later answers does](http://stackoverflow.com/a/19235249/104223). I am not sure which one the OP used though. – Leigh Nov 05 '13 at 22:02
  • Oh, I missed that one... but `arraySort()` doesn't work the way that code suggests. The callback needs to return -1,0,1 not a boolean. However at some stage in CF10's life the behaviour changed. See http://cfmlblog.adamcameron.me/2013/07/ok-im-very-confused-arraysort-with.html – Adam Cameron Nov 05 '13 at 22:25
  • *The callback needs to return -1,0,1* Ah, yes that make sense. Just like a java comparator. – Leigh Nov 06 '13 at 02:34

2 Answers2

2

ColdFusion 10 has built-in customised array sorting using a callback. The docs for arraySort() didn't mention this, but I've just updated them with an example. My example there doesn't show a compound sort like you require, but it's easy enough:

<cfscript>
comparator = function(e1, e2){
    e1.row += 0; // need to make sure it's not a string for the Java method call below
    var rowCompare = e1.row.compareTo(e2.row + 0);
    if (rowCompare !=0){
        return rowCompare;
    }
    e1.col += 0;
    return e1.col.compareTo(e2.col + 0);
};

data = [
    {row=3, col=3}, {row=3,col=2}, {row=3, col=1},
    {row=2, col=3}, {row=2,col=2}, {row=2, col=1},
    {row=1, col=3}, {row=1,col=2}, {row=1, col=1}
];

writeDump(var=data);
arraySort(data, comparator);
writeDump(var=data);
</cfscript>

This leverages that CF numerics are java.lang.Double objects.

Adam Cameron
  • 29,677
  • 4
  • 37
  • 78
0
<cfscript>

    //ColdFusion 10 only supports this new types of struct declaration
    recordArr = [
            {col: 1,dataid:48,identifier:1,row:1,size_x:4,size_y:1},
            {col: 1,dataid:42,identifier:2,row:2,size_x:2,size_y:1},
            {col: 3,dataid:45,identifier:3,row:2,size_x:2,size_y:1}
    ];

    //ColdFusion 10 only supports this new queryNew() functionality
    queryObj = queryNew("col,dataid,identifier,row,size_x,size_y",
                        "Integer,Integer,Integer,Integer,Integer,Integer",
                        recordArr);
</cfscript>

<!--- Here it comes our favourite cfquery tag. We can apply order by clause 
as per our wish --->
<cfquery name="ordredResult" dbtype="query">
    SELECT * FROM queryObj ORDER BY row ASC, col ASC
</cfquery>

<!--- Here is the expected result --->
<cfdump var="#ordredResult#">
Roul
  • 945
  • 1
  • 12
  • 34