miva_array_sort()

 
This function will sort an array structure
Syntax
miva_array_sort( aggregate var, callback, data var )
Returns the number of array elements in the aggregate array structure after sorting.
  • Aggregate: The array that will be sorted. (the aggregate will be physically altered on return)
  • Callback: The name of a user function that must exist in your program, defined as Callback(left var, right var, data var)
  • Data: Not directly used in the miva_array_sort(), the value will be passed to the Callback function.
User Annotations: miva_array_sort
Jonathan Burchmore : jburchmore at, mivamerchant d0t com
06/14/2012 14:34 p.m.
In Scott's example, his callback is (unintentionally, I assume) using the default serializer, which results in the first (alphabetically) member's data coming first.  This explains the results he is seeing.

If you want to compare specific members, you should do so explicitly.  Here's an example:
<MvFUNCTION NAME = "SortCustomFieldList_Callback" PARAMETERS = "left var, right var, data var" STANDARDOUTPUTLEVEL = "">
    <MvASSIGN NAME = "l.left_name" VALUE = "{ tolower( l.left:name ) }">
    <MvASSIGN NAME = "l.right_name" VALUE = "{ tolower( l.right:name ) }">

    <MvIF EXPR = "{ l.left_name LT l.right_name }">     <MvFUNCTIONRETURN VALUE = "-1">
    <MvELSEIF EXPR = "{ l.left_name GT l.right_name }"> <MvFUNCTIONRETURN VALUE = "1">
    </MvIF>

    <MvFUNCTIONRETURN VALUE = "">
</MvFUNCTION>
Scott McC : cyberfunkr at, yahoo d0t com
02/04/2011 22:27 p.m.
In my testing, it looks like the miva_array_sort() function will only sort on the alphabetically superior structure name. So if you have an array like:

g.product[1]:name="apple"
g.product[1]:price="1.50"
g.product[1]:color="green"
g.product[1]:code="grannysmith"

It will sort on :code.

So to get around it you can do one of two things:
1) As you load in your array, double assign price; once as ':price' and once as ':a' and then sort.
or
2) Load in your array, loop through it adding a new structure element called ':a' that is a duplicate of ':price', sort, and then optionally remove ':a'

Version one is quicker as it's less loops through an array.

Here is a clunky function to use method 2, including the callback:
<MvFUNCTION NAME = "Miva_Array_Sort_By" PARAMETERS = "element, array var" STANDARDOUTPUTLEVEL = "">
	<MvASSIGN NAME = "l.max" VALUE = "{ miva_array_max( l.array ) }">
	<MvASSIGN NAME = "l.pos" VALUE = "{ miva_array_min( l.array ) }">

	<MvWHILE EXPR = "{ l.pos LE l.max }">
		<MvASSIGN NAME = "l.array" INDEX = "{ l.pos }" MEMBER = "a" VALUE = "{ miva_variable_value( 'l.array[' $ l.pos $ ']:' $ l.element ) }">
		<MvASSIGN NAME = "l.pos" VALUE = "{ miva_array_next( l.array, l.pos ) }">
	</MvWHILE>

	<MvASSIGN NAME = "l.sort" VALUE = "{ miva_array_sort( l.array, 'Sort_Callback', l.null ) }">

	<MvASSIGN NAME = "l.pos" VALUE = "{ miva_array_min( l.array ) }">
	<MvWHILE EXPR = "{ l.pos LE l.max }">
		<MvASSIGN NAME = "l.array" INDEX = "{ l.pos }" MEMBER = "a" VALUE = "">
		<MvASSIGN NAME = "l.pos" VALUE = "{ miva_array_next( l.array, l.pos ) }">
	</MvWHILE>

	<MvFUNCTIONRETURN VALUE = "{ l.sort }">
</MvFUNCTION>

<MvFUNCTION NAME = "Sort_Callback" PARAMETERS = "left var, right var, data var" STANDARDOUTPUTLEVEL = "">
    <MvIF EXPR = "{ l.left LT l.right }">
        <MvFUNCTIONRETURN VALUE = "-1">
    <MvELSEIF EXPR = "{ l.left GT l.right }">
        <MvFUNCTIONRETURN VALUE = "1">
    <MvELSE>
        <MvCOMMENT> l.left EQ l.right </MvCOMMENT>
        <MvFUNCTIONRETURN VALUE = "">
    </MvIF>
</MvFUNCTION>

<MvASSIGN NAME = "l.sort" VALUE = "{ Miva_Array_Sort_By( 'price', l.struct ) }">