outline-style sorting algorithm
Eric Brunel
eric_brunel at despammed.com
Mon Apr 19 11:30:58 EDT 2004
Max M wrote:
> jwsacksteder at ramprecision.com wrote:
> > I have a need to sort a list of elements that represent sections of a
> > document in dot-separated notation. The built in sort does the wrong
> thing.
>
> Not really. You are giving it a list of strings, and it sort those
> alphabetically. That seems like the right thing to me ;-)
>
> > This seems a rather complex problem and I was hoping someone smarter
> than me
> > had already worked out the best way to approach this. For example,
> consider
> > the following list-
>
> >>>>foo
> >
> > ['1.0', '1.0.1', '1.1.1', '1.2', '1.9', '1.10', '1.11', '1.20',
> '1.20.1',
> > '1.30']
>
> You need to convert them to another datatype first. Your best bet here
> would be a list or a tuple, as they can map directly to your data.
>
> '1.0.1'.split('.') == [1,0,1]
[snip]
Nope:
'1.0.1.split('.') == ['1', '0', '1']
So the int's are still represented as strings and it does not solve the OP's
problem:
>>> foo = ['1.0', '1.0.1', '1.1.1', '1.2', '1.9', '1.10', '1.11', '1.20',
'1.20.1', '1.30']
>>> bar = [x.split('.') for x in foo]
>>> bar
[['1', '0'], ['1', '0', '1'], ['1', '1', '1'], ['1', '2'], ['1', '9'], ['1',
'10'], ['1', '11'], ['1', '20'], ['1', '20', '1'], ['1', '30']]
>>> bar.sort()
>>> bar
[['1', '0'], ['1', '0', '1'], ['1', '1', '1'], ['1', '10'], ['1', '11'], ['1',
'2'], ['1', '20'], ['1', '20', '1'], ['1', '30'], ['1', '9']]
And the 1.20.something are still before 1.9
What you need to do is explicitely convert to integers the strings in the list
resulting from the split. Here is the shortest way to do it
>>> bar = [map(int, x.split('.')) for x in foo]
>>> bar
[[1, 0], [1, 0, 1], [1, 1, 1], [1, 2], [1, 9], [1, 10], [1, 11], [1, 20], [1,
20, 1], [1, 30]]
Now you can sort:
>>> bar.sort()
>>> bar
[[1, 0], [1, 0, 1], [1, 1, 1], [1, 2], [1, 9], [1, 10], [1, 11], [1, 20], [1,
20, 1], [1, 30]]
Hooray! We've got the result we wanted. Now, convert integers back to string and
re-join everything:
>>> foo = ['.'.join(map(str, x)) for x in bar]
>>> foo
['1.0', '1.0.1', '1.1.1', '1.2', '1.9', '1.10', '1.11', '1.20', '1.20.1', '1.30']
That's what we expected...
HTH
--
- Eric Brunel <eric (underscore) brunel (at) despammed (dot) com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com
More information about the Python-list
mailing list