2

I am trying to sort values alphabetically between open and closed parenthesis like the following

(m,b,l,a(d,g,c(l,e)),f(k,g,h(i)),j) and I would like a output of

(a(c(e,l),d,g),b,f(g,h(i),k),j,l,m) in the sorted order.

I have done some coding and it is going wacky. I was able to sort innermost parenthesis and but not able continue.

indexofparen = []
for i, c in enumerate(s):
    if c == "(":
        indexofparen.append(i)
##print(indexofparen)
closeparen = []
for i, c in enumerate(s):
    if c == ")":
        closeparen.append(i)
##print(closeparen)
parenindex=s.rindex("(")
##print(parenindex)
matchparen=s.index(")")-1
##print(matchparen)
list_val = s[s.rindex("(")+1:s.index(")")].split(",")
##print("Before:", list_val)
for passnum in range(len(list_val)-1, 0, -1):
    for i in range(passnum):
        if list_val[i] > list_val[i+1]:
          list_val[i], list_val[i+1] = list_val[i+1], list_val[i]
##print(list_val)
s1=s[:parenindex] + "(" + ','.join(str(e) for e in list_val) + ")" + s[matchparen:]
##print(s1)
s2 = s[indexofparen[1]+1:closeparen[2]]

After this I am kind of loopy. Any help is to refine and go about sorting this hard problem is appreciated. Thank you very much for the time spent in helping me. Much appreciated.

Xavier
  • 33
  • 3
  • Are all values unique, or could there be several of the same (both at the same and different level)? – JohanL Apr 25 '17 at 22:18
  • [parsing nested parentheses in python, grab content by level](http://stackoverflow.com/q/4284991/2823755) - might be a good place to start. – wwii Apr 25 '17 at 23:03

1 Answers1

3

This was fun:

In [55]: def sort_key(t):
    ...:     if isinstance(t, tuple):
    ...:         return t
    ...:     return (t,)
    ...:

In [56]: def recursive_sort(x):
    ...:     gen = (recursive_sort(t) if isinstance(t, tuple) else t for t in x)
    ...:     return tuple(sorted(gen, key=sort_key))
    ...:

In [57]: print(x)
('m', 'b', 'l', 'a', ('d', 'g', 'c', ('l', 'e')), 'f', ('k', 'g', 'h', ('i',)), 'j')

In [58]: print(recursive_sort(x))
('a', 'b', ('c', 'd', ('e', 'l'), 'g'), 'f', ('g', 'h', ('i',), 'k'), 'j', 'l', 'm')

The "key" is in the key argument, which makes sure you are comparing tuples and takes care of the lexicographic aspect of the sort. Then, it is simply recursively sorting the elements if they are a tuple or not.

EDIT

Whoops! Just realized that you wanted to sort a string. Well, since I've grown attached to my solution, here's an ugly hack to salvage it:

In [60]: import re

In [61]: import ast

In [62]: def to_tuple(s):
    ...:     s = re.sub(r"([a-zA-Z])([\(\)])",r"\1,\2",s)
    ...:     s = re.sub(r"([a-zA-Z])",r"'\1'",s)
    ...:     return ast.literal_eval(s)
    ...:

In [63]: def to_string(t):
    ...:     return str(t).replace("',)", "')").replace("'",'')
    ...:

In [64]: s = "(m,b,l,a(d,g,c(l,e)),f(k,g,h(i)),j)"

And finally:

In [65]: print(t)
('m', 'b', 'l', 'a', ('d', 'g', 'c', ('l', 'e')), 'f', ('k', 'g', 'h', ('i',)), 'j')

In [66]: to_string(recursive_sort(t))
Out[66]: '(a, b, (c, d, (e, l), g), f, (g, h, (i), k), j, l, m)'
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • This is the output I got when I ran your code and not the output you have shown. 'x=(m,b,l,a(d,g,c(l,e)),f(k,g,h(i)),j) print(x) ((, (, (, (, (, ), ), ), ), ), ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, a, b, c, d, e, f, g, g, h, i, j, k, l, l, m) – Xavier Apr 26 '17 at 13:57
  • This is the output I got when I ran your code and not the output you have shown. `print(x) x=(m,b,l,a(d,g,c(l,e)),f(k,g,h(i)),j) print(to_string(recursive_sort(x))) ((, (, (, (, (, ), ), ), ), ), ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, a, b, c, d, e, f, g, g, h, i, j, k, l, l, m)` – Xavier Apr 26 '17 at 14:05
  • @Xavier these aren't reproducible examples... `x=(m,b,l,a(d,g,c(l,e)),f(k,g,h(i)),j) ` is not valid Python unless `a`,`b`, `c` etc. are defined... – juanpa.arrivillaga Apr 26 '17 at 15:47