Message Boards Message Boards

0
|
6744 Views
|
5 Replies
|
2 Total Likes
View groups...
Share
Share this post:

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

Posted 10 years ago

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.

POSTED BY: Mario Weitzer
5 Replies

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 BY: Udo Krause

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 BY: Ilian Gachevski

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 BY: Udo Krause

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 BY: Bruce Miller

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)"}
POSTED BY: Udo Krause
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract