Question on sorting

Peter Otten __peter__ at web.de
Wed Dec 1 12:37:15 CET 2004


Lad wrote:

> wes weston <wweston at att.net> wrote in message
> news:<0gKqd.72252$7i4.43429 at bgtnsc05-news.ops.worldnet.att.net>...
>> Lad wrote:
>> > Hi,
>> > I have a file of records of 4 fields each.
>> > Each field is separated by a semicolon. That is
>> > 
>> > Filed1;Ffield2;Field3;Field4
>> > 
>> > But there may be also empty records such as
>> > ;;;;
>> > (only semicolons).
>> > 
>> > For sorting I used
>> > #################
>> > lines = file('Config.txt').readlines()# a file I want to sort
>> > lines.sort()
>> > ff=open('ConfigSorted.txt','w')# sorted file
>> > ff.writelines(lines)
>> > ff.close()
>> > ###############
>> > It was sorted but empty records were first. I need them to be last(at
>> > the end of the file). How can I do that?
>> > 
>> > Thanks for help
>> > Lad
>> 
>> Lad,
>>     The sort call can have a function name as an arg. You
>> could do:
>> 
>> def mycompare(s1,s2):
>> #return -1 to put s1's at front; 1 to put s1's at back; 0 for a tie
>> #if s1==";;;;" and s2<>";;;;": return 1
>> 
>> lines.sort(mycompare)
>> 
> Wes,
> Thank you for reply. But I do not understand mycompare function. Can
> you please explain to me how it should work? Thanks

compare(a, b) is just a function for comparing two items/lines. I must
return -1 if a<b, +1 if a>b, and 0 if a==b. For example the following
compare moves the ";;;;" records to the end and keeps the order of others
unaffected:

>>> items = [";;;;", ";a;b;;", ";b;a;;", "a;b;c;d;e", "a;;;d;e"]
>>> def compare(a, b):
...     return cmp(a == ";;;;", b == ";;;;") or cmp(a, b)
...
>>> items.sort(compare)
>>> items
[';a;b;;', ';b;a;;', 'a;;;d;e', 'a;b;c;d;e', ';;;;']

As Eddie Corns pointed out, you left some doubt whether that is really what
you want. Here is a more complex compare() that handles the lines as
columns split by ";" and puts empty columns last in the sorting order:

>>> def key(row):
...     return [(not col, col) for col in row.split(";")]
...
>>> def compare(a, b):
...     return cmp(key(a), key(b))
...
>>> items.sort(compare)
>>> items
['a;b;c;d;e', 'a;;;d;e', ';a;b;;', ';b;a;;', ';;;;']

If you are on Python 2.4, you don't need the compare() detour and can use
key() directly:

>>> items.sort(key=key)
>>> items
['a;b;c;d;e', 'a;;;d;e', ';a;b;;', ';b;a;;', ';;;;']

Finally, the ";;;;" lines don't seem to carry any information - why not
filter them out completely?

>>> items = [line[:-1] for line in file("cfg.txt", "U") if line != ";;;;\n"]


Peter




More information about the Python-list mailing list