No BSD License  

Highlights from
SORTN - sort textual lists

from SORTN - sort textual lists by Oren Yagev
Sort text lists containing letters and numbers.

sortn(orgArr)
function [sortedArr,finalIndex] = sortn(orgArr)

% SORTN - Sort cell array or char array in textual and numerical mode.
%               Primary sort by first letter, secondary by second letter and so on.
%               Numbers are considered an numerical values.
%               
%               Sorting Rules:
%                           'a' comes before 'b' and so on.
%                           Numbers come before letters
%                           Numbers are compared according to their value
%                           Short string comes before a long one (when first chars are identical) 
%                           Ignore characters that are not letters or
%                           numbers.
%                           SORTN is NOT case sensitive.
%
%               The main interest in this function is that it can sort
%               numbers with text, so string like 'a60' comes before 'a100'
%
%[SORTED_CELL_ARRAY , INDEXES] = SORTN(CELL_ARRAY) - Sorts the cells array
%                or char array and returns sorted cell array and indexes
%                vector of new arranged cell array.
%
%EXAMPLE:
%               cell_arr = {'abcde54f';
%                                       'aabde54f'}
%
%              [sorted,indexes]=sortn(cell_arr)
%
%               sorted = 
%                                   'aabde54f'
%                                   'abcde54f'
%               indexes = 
%                                       2
%                                       1                          
%
%
%
%               cell_arr = {'abcde154f';
%                                       'abcde54f'}
%
%              [sorted,indexes]=sortn(cell_arr)
%
%               sorted = 
%
%                                   'abcde54f'
%                                   'abcde154f'
%               indexes =
%
%                                   2
%                                   1    
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



if ischar(orgArr)   %function works with cell array, so if char input, convert to cell array
    tempList = lower(orgArr);
    orgArr = cellstr(orgArr);
else
    tempList = char(lower(orgArr));
end

finalIndex = (1:length(orgArr))';   %create the index vector to be changed
g = {};
for i=1:size(tempList)  %go over all strings and break each one to single letters and numbers
    tempCellArr = breakString(tempList(i,:));   %break one string from the cell array
    g = AssignCellArray(tempCellArr, g);    %add the breaked string to cell matrix
end
%[g,indexes] = SortByColumn2(g,5);
for i=size(g,2):-1:1    %go over cell matrix of breaked strings and sort is from last column to the first

    [g,indexes] = SortByColumn(g,i);    %sort the i column
    
    orgArr = orgArr(indexes);   %update cell array order by the indexes
    finalIndex = finalIndex(indexes);   %update final index order
    
end

sortedArr =orgArr ;


function [sortedArr,indexes] = SortByColumn(arr,column);    
%this function sort each column of the breaked cell-matrix
%sorting is done by converting each textual number to its real value
%and later assign every letter its ascii value plus the maximum of all
%numbers. 
%the sorting is pure numeric (Matlab sort) so numbers are always before
%letters.

tempColumn = zeros(size(arr,1),1);
for i=1:length(tempColumn)
    if ~isempty(str2num(char(arr(i,column)))); %finds all numbers including non-real numbers
        tempColumn(i) = str2num(char(arr(i,column)))+1; %assign numbers to the vactor
    end
end
maxNum = max(tempColumn);
u2 = isletter(char(arr(:,column))); %find all letters
tempColumn(u2) = char(arr(u2,column)) + maxNum; %assign numerical representation of letters that is bigger then the numbers

[tempSort,indexes] = sort(tempColumn);
sortedArr = arr(indexes,:);



function newArr = AssignCellArray(assignmentVector, assignTo)
%this function helps adding cell-arrays to the breaked strings cell-matrix


assignToSize = size(assignTo,2);
assignmentVectorSize = length(assignmentVector);
if assignToSize==0
    newArr = assignmentVector;
    
elseif (assignToSize==assignmentVectorSize)
    newArr = [assignTo;assignmentVector];
elseif (assignToSize>assignmentVectorSize)
    assignmentVector((assignmentVectorSize+1):assignToSize)={' '};
    newArr = [assignTo;assignmentVector];
else
    assignTo(:,(assignToSize+1):assignmentVectorSize)={' '};
    newArr = [assignTo;assignmentVector];
end


function groups = breakString(stringToBreak)
%this function breaks a string to its single letters and numbers,
%producing cell array for a single string.

if ~ischar(stringToBreak)   %convert to char array
    tempString = char(stringToBreak);
else
    tempString=stringToBreak;
end
counter = 1;
i=1;
groups = {};
while i<=length(tempString) %go over all chars in the string
    if  ~isletter(tempString(i)) & isempty(str2num(tempString(i)))   %tempString(i)==' '   %Skip spaces
        i=i+1;
        continue;
    end
    if isempty(str2num(tempString(i)))  %in case of a letter - just add it to the array
        groups(counter)={tempString(i)};
        counter = counter + 1;
        i = i + 1;
    else
        groups(counter) = {tempString(i)};
        i = i+1;
        while (i<=length(tempString) & ~isempty(str2num(tempString(i))))    %in case of number,
            %add it to the array and search for following numbers
            groups(counter)={[char(groups(counter)) tempString(i)]};
            i = i + 1;
        end
        counter = counter + 1;
    end
end

Contact us at files@mathworks.com