[comp.lang.icon] complicated sort

nowlin@ihuxy.UUCP (01/04/88)

> I need to sort a list of records according to complicated sort criteria,
> The standard icon sort() routine is not making this task easy.  What I need
> is something more like the C library qsort routine that lets me provide my
> own comparison routine.
> 
> Is there any hope of my finding something like this in icon, or am I
> missing some elegant way to do this with the existing sort() routine?
> 
>   --dave yost

I'm not sure this is what you had in mind but the procedure enclosed is
handy for sorting records and can be modified to work with your own
comparison routines fairly easily.  I don't know of any way to use the
builtin sort() for anything other than standard types.

This recsort() procedure only sorts on one field of a record but it
wouldn't be too hard to pass it a list of the fields in the record that
should be sorted on instead of a single value.  The way the intermediate
table of records is maintained will make it fairly easy to sort on multiple
keys.  Hope this is helpful.  (Sorry for the lack of comments.)

Jerry Nowlin
(...!ihnp4!ihuxy!nowlin)

# This example program sorts a UNIX style password file.  The first
# argument to the program should be the field in each password entry to
# sort on.  The program has a limit of the first 20 entries built in but
# it can be removed to test the program on the whole password file.  The
# program uses the recsort() procedure to sort a list of records.

record	passwd(name,pass,uid,gid,info,logdir,shell)

procedure main(args)

	if *args = 0 then stop("I need a numeric field index to sort on")

	users := []

	in := open("/etc/passwd","r")

	every line := !in\20 do line ? {

		user := passwd()
		user.name := tab(upto(':')) & move(1)
		user.pass := tab(upto(':')) & move(1)
		user.uid := tab(upto(':')) & move(1)
		user.gid := tab(upto(':')) & move(1)
		user.info := tab(upto(':')) & move(1)
		user.logdir := tab(upto(':')) & move(1)
		user.shell := tab(0)
		put(users,user)

	}

	close(in)

	write("UNSORTED: ",image(users)," ",image(users[1]))
	every user := !users do write(	user.name," : ",
					user.pass," : ",
					user.uid," : ",
					user.gid," : ",
					user.info," : ",
					user.logdir," : ",
					user.shell)

	stuff := recsort(users,!args)

	write("\nSORTED: ",image(stuff)," ",image(stuff[1]))
	every user := !stuff do write(	user.name," : ",
					user.pass," : ",
					user.uid," : ",
					user.gid," : ",
					user.info," : ",
					user.logdir," : ",
					user.shell)

end

procedure recsort(recs,index)

	tempt := table()

	every rec := !recs do
		(/tempt[rec[index]] := [ rec ]) | put(tempt[rec[index]],rec)

	templ := sort(tempt,1)

	newrecs := []

	every pair := !templ do
		every put(newrecs,!pair[2])

	return newrecs

end