Quicksort on a container

Good evening

Today, I wanted to fix the sorting in the Dynamics Ax 4.0x Active Directory user import wizard. I wanted the AD users sorted by their Windows alias. There are mutiple tools in DAX to sort records (in particular: the RecordSortedList and temporary tables) but I couldn’t find anything to sort lists, arrays or containers. At first I thought of using the .Net Framework’s Collections.SortedList, but the SortedList.add() method didn’t seem to work. So I dug up the quicksort algorithm from a java website and coded the following method.

‘_qsc’ is basically a container that contains one or many ‘[str]’. It would look like this ‘[[str], [str], [str], …]’. The reason I didn’t implement this with a simpler ‘[str, str, str, …]’ is that I wanted to be able to sort a container by an str key, but still allowing for another value or set of values to follow.

You could easily adapt the code to sort by ‘str’ a container that would look like this ‘[[str, anytype], [str, anytype], [str, anytype], …]’. That would make it a kind of Map(Types::String, Types::Anytype). You can put the following method in your Global class if you want to call it from anywhere.

Also note that containers are passed by value, so this will potentially take a lot of memory for containers larger than a few hundred elements. Implementing the sorting using a class like DAX’s Array class would definitely take less ram at runtime since only one instance of the class would be needed throughout (you would need to modify my method though as you would need to remove the return type and return value since methods recursive by reference don’t need to return anything).

Note: ‘gl00mie’ from AxForum.info rightfully suggested I use a map instead of containers since map keys are always sorted (I had never noticed), as my following code creates multiple container duplicates and junks up memory.
public static container quickSortStrContainer(
    container _qsc,
    int _qsstart = 1,
    int _qsend = conlen(_qsc))
{
    int qsi = _qsstart
    int qsj = _qsend;
    str qsx;
    str qsKey;
    ;

    [qsx] = conpeek(_qsc, (_qsstart +_qsend)/2);

    do
    {
        [qsKey] = conpeek(_qsc, qsi);
        while (qsKey < qsx)
        {
            qsi++;
            if (qsi <= conlen(_qsc))
            {
                [qsKey] = conpeek(_qsc, qsi);
            }
            else
            {
                break;
            }
        }

        [qsKey] = conpeek(_qsc, qsj);
        while (qsKey > qsx)
        {
            qsj–;
            if (qsi > 0)
            {
                [qsKey] = conpeek(_qsc, qsj);
            }
            else
            {
                break;
            }
        }

        if (qsi <= qsj)
        {
            [qsKey] = conpeek(_qsc, qsi);
            _qsc = conpoke(_qsc, qsi, conpeek(_qsc, qsj));
            _qsc = conpoke(_qsc, qsj, [qsKey]);
            qsi++;
            qsj–;
        }
    }
    while (qsi <= qsj);

    if (_qsstart < qsj)
    {
        _qsc = quickSortStrContainer(_qsc, _qsstart, qsj);
    }
    if (qsi < _qsend)
    {
        _qsc = quickSortStrContainer(_qsc, qsi, _qsend);
    }

    return _qsc;
}

This entry was posted in Dynamics Ax 4.0x. Bookmark the permalink.