# How can I order a list of strings in Mathematica lexicographically?

Posted 9 years ago
6083 Views
|
5 Replies
|
2 Total Likes
|
 Whatever I try, nothing works. Sort[Union[{"(+3k-1,-4n/3-3m+k-7/3)", "(+3k+1,-n-m+k)", "(+3k-1,-n-m+k-1)"}], OrderedQ[{#1, #2}] &] gives {"(+3k-1,-4n/3-3m+k-7/3)", "(+3k+1,-n-m+k)", "(+3k-1,-n-m+k-1)"} which makes no sense to me. "(+3k+"something should not be between two "(+3k-"somethings unless the length comes first to decide the ordering. But then the shortest one shouldn't be in the middle. I can't believe that there is no built in way in Mathematica to do this right.
5 Replies
Sort By:
Posted 9 years ago
 I can't believe that there is no built in way in Mathematica to do this right. It's possible to convert forth and back to character code, but then there is the problem, that the order of lists is undefined In[32]:= {40, 43, 51, 107, 45, 49, 44, 45, 52, 110, 47, 51, 45, 51, 109, 43, 107, 45, 55, 47, 51, 41} > {40, 43, 51, 107, 43, 49, 44, 45, 110, 45, 109, 43, 107, 41} Out[32]= {40, 43, 51, 107, 45, 49, 44, 45, 52, 110, 47, 51, 45, 51, 109, 43, 107, 45, 55, 47, 51, 41} > {40, 43, 51, 107, 43, 49, 44, 45, 110, 45, 109, 43, 107, 41} so let's do something simple minded In[36]:= Clear[weitzerOrder] weitzerOrder[l1_List?VectorQ, l2_List?VectorQ] := Block[{o = 1, len1 = Length[l1], len2 = Length[l2]}, While[l1[[o]] == l2[[o]] && o <= Min[len1, len2], o++]; If[l1[[o]] < l2[[o]], True, (* else *) If[o > len1, True, (* else *) False ] ] ] FromCharacterCode /@ Sort[ToCharacterCode /@ {"(+3k-1,-4n/3-3m+k-7/3)", "(+3k+1,-n-m+k)", "(+3k-1,-n-m+k-1)"}, weitzerOrder[#1, #2] &] Out[38]= {"(+3k+1,-n-m+k)", "(+3k-1,-4n/3-3m+k-7/3)", "(+3k-1,-n-m+k-1)"} 
Posted 9 years ago
 The precedence being the same doesn't quite explain the result, because + and - do get sorted (based on their long names, I believe, though that is undocumented). In[2]:= Sort[{"+", "-"}] Out[2]= {"-", "+"} 
Posted 9 years ago
 But the test fails despite Sort works (anti-konform to the character code) In[1]:= "+" < "-" Out[1]= "+" < "-" In[2]:= {"+"} < {"-"} Out[2]= {"+"} < {"-"} In[8]:= ToCharacterCode["+"] < ToCharacterCode["-"] Out[8]= {43} < {45} In[12]:= weitzerOrder[ToCharacterCode["+"], ToCharacterCode["-"]] Out[12]= True 
Posted 9 years ago
 This took digging. In the reference page for Sort (http://reference.wolfram.com/language/ref/Sort.html), under Details, Sort orders strings as in a dictionary, with uppercase versions of letters coming after lowercase ones. Sort places ordinary letters first, followed in order by script, Gothic, double-struck, Greek, and Hebrew. Mathematical operators appear in order of decreasing precedence. $+$ and $-$ have the same precedence. (http://reference.wolfram.com/language/tutorial/OperatorInputForms.html, half-way down.) To get these in ASCII order, you will have to write your own function.
Posted 9 years ago
 To get these in ASCII order, you will have to write your own function. In[18]:= Clear[WRule] WRule = {"-" -> "WMinus", "+" -> "WPlus"}; StringReplace[ Sort[StringReplace[{"(+3k-1,-4n/3-3m+k-7/3)", "(+3k+1,-n-m+k)", "(+3k-1,-n-m+k-1)"}, WRule], OrderedQ[{#1, #2}] &], Reverse /@ WRule] Out[20]= {"(+3k-1,-4n/3-3m+k-7/3)", "(+3k-1,-n-m+k-1)", "(+3k+1,-n-m+k)"} or if the minus should appear later In[21]:= Clear[WRule] WRule = {"-" -> "WLast", "+" -> "WFirst"}; StringReplace[ Sort[StringReplace[{"(+3k-1,-4n/3-3m+k-7/3)", "(+3k+1,-n-m+k)", "(+3k-1,-n-m+k-1)"}, WRule], OrderedQ[{#1, #2}] &], Reverse /@ WRule] Out[23]= {"(+3k+1,-n-m+k)", "(+3k-1,-4n/3-3m+k-7/3)", "(+3k-1,-n-m+k-1)"}