How can I sort a string both alphabetically and numerically?
162 views (last 30 days)
Show older comments
I'm using a list box that displays the names of the shapes I am storing in a shapefile. I'm using the sort function to list them alphabetically. This works great, but when I get to something above 9 it doesn't work quite the way I want it to. For example, my list box looks something like this:
Circle 1
Circle 10
Circle 11
Circle 12
Circle 13
Circle 2
Circle 3
Circle 4
Circle 5
Circle 6
Circle 7
Circle 8
Circle 9
Ellipse 1
Ellipse 2
Rectangle 1
.
.
.
I'd like some way to make it so that the Circles above 9 follow after the 9 instead of the 1.
2 Comments
Oleg Komarov
on 17 Jul 2012
One general approach is to pad with zeros:
Circle 01
Circle 02
...
Circle 10
Now if you have hundreds, then
Circle 001
...
Jan
on 17 Jul 2012
Oleg, that's true. The leading zeros let the numerical order be the same as the alphabetical order.
Accepted Answer
Teja Muppirala
on 17 Jul 2012
Very ugly, but works:
UnsortedText = {'BBB 1'; 'AAA 10'; 'AAA 9'; 'AAA 1'; 'BBB 2'; 'BBB 19'; 'BBB 9'; 'CCC 0'; 'CCC 9' ;'CCC 80'; 'CCC 7'};
R = cell2mat(regexp(UnsortedText ,'(?<Name>\D+)(?<Nums>\d+)','names'));
tmp = sortrows([{R.Name}' num2cell(cellfun(@(x)str2double(x),{R.Nums}'))]);
SortedText = strcat(tmp(:,1) ,cellfun(@(x) num2str(x), tmp(:,2),'unif',0))
There's got to be a simpler way to do this...
More Answers (4)
Ryan
on 17 Jul 2012
FEX Submission "ASORT: A Pedestrian Alphanumeric String Sorter" works somewhat. I was able to sort something such as:
A = {'A 1', 'A 9', 'A 10', 'A 5'}; % In the order you asked for
But something such as:
A = {'A 1', 'B 10', 'A 4', 'B 2'};
Resulted in:
ans = A 1, B 2, A 4, B 10
There may be a better alphanumeric string sorter in the FEX that I missed in my quick search and that particular submission has some additional settings. You could sort each shape individually then concatenate back into one array if this function ends up as your best option.
0 Comments
Azzi Abdelmalek
on 17 Jul 2012
Edited: Azzi Abdelmalek
on 17 Jul 2012
list=strvcat('cir 1','cir 2','cir 10','cir 11',...
'cir 12','d 1','d 2','d 10','d 11','d 12','ee 15','dhgt 9','azs 45')
[n,m]=size(list);list1=[];list2=[];listn=[];
for k=1:n;
index = find(isstrprop(list(k,:), 'digit'), 1)
list1=strvcat(list1,list(k,1:index-1));
list2=strvcat(list2,list(k,index:end));
listn=[listn;str2num(list(k,index:end))];
end
list1c=cellstr(list1);
list2c=cellstr(list2);
listc=sortrows([list1c list2c])
listc1=listc(:,1);
list2n=str2num(char(listc(:,2)))
result1=[];k=1;result2=[];
while k<=n
ind=strmatch(listc1(k),listc1);
n1=min(ind);n2=max(ind);
result1=[result1 ;listc1(n1:n2) ]
result2=[result2; cellstr(num2str(sort(list2n(n1:n2))))]
k=k+length(ind)
end
res1=char(result1);res2=char(result2);res=[];
for k=1:n
res=strvcat(res,[strtrim(res1(k,:)) ' ' strtrim(res2(k,:))] )
end
%the result is en res variable
0 Comments
Marvin Seifert
on 22 Apr 2020
Its an old question but still maybe I found a simpler solution:
(This works only if there is only one number in the string)
Numbers = zeros(1,length(UnsortedText));
for ii = 1:length(UnsortedText)
log = isstrprop(UnsortedText{ii},'digit')
string_name = UnsortedText{ii};
%This creates a new array only containing the numbers
numbers(ii) = string(string_name(log));
end
[~, a_order] = sort(numbers);
SortedText = UnsortedText(a_order);
0 Comments
Stephen23
on 27 Apr 2023
By far the simplest approach is to download the NATSORT function:
and then use it like this:
C = {'BBB 1'; 'AAA 10'; 'AAA 9'; 'AAA 1'; 'BBB 2'; 'BBB 19'; 'BBB 9'; 'CCC 0'; 'CCC 9' ;'CCC 80'; 'CCC 7'}
D = natsort(C)
0 Comments
See Also
Categories
Find more on Creating and Concatenating Matrices in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!