MultiSort
public domain. no guarentees, use it as you wish.
author: kobi
the needed functions follow.
purpose: sorts a list of objects based on multiple criteria, the criteria are "fields" in the object (cells in the sequence)
It was simple to produce thanks to the built in custom_sort.
the passed 'fields' argument is assumed to be a normal enum (starts from 1), for accessing the field index.
-- multi_sort.e namespace multi_sort include assert.e include std/sort.e include conditions.e function compare_two(sequence a, sequence b, sequence fields) require(all_positive(fields),"fields must be positive") for i=1 to length(fields) do integer field = fields[i] integer cmp = compare(a[field],b[field]) if cmp != 0 then return cmp end if end for return 0 -- equal. end function public function multisort(sequence seq, sequence fields_order) return custom_sort(routine_id("compare_two"), seq, {fields_order}) end function
-- assert.e namespace assert include std/error.e public procedure assert(integer x, sequence text = "") if x = 0 then crash(text) end if end procedure public procedure require(integer x,sequence text="") assert(x,text) end procedure
-- conditions.e namespace conditions include seq_ops.e function positive(atom a) return a > 0 end function public function all_positive(sequence sequ) integer rid = routine_id("positive") return all(sequ,rid) end function function notneg(atom a) return not (a < 0) end function public function all_uint(sequence sequ) integer rid = routine_id("notneg") return all(sequ,rid) end function
-- seq_ops.e include assert.e public function all(sequence seq, integer func) for i=1 to length(seq) do if call_func(func,{seq[i]}) = 0 then return 0 end if end for return 1 end function
Example and unit tests:
-- t_multi_sort.ex include std/unittest.e include multi_sort.e include conditions.e type house(sequence seq) return length(seq)=4 and all_uint(seq) end type enum CHAIR, DESK, ROOMS, WALL -- CHAIR, DESK, ROOMS, WALL house a = {3, 4, 2, 1} house b = {4, 1, 2, 2} house c = {5, 4, 3, 1} house d = {3, 4, 2, 3} test_equal("multi sort 1", { {3,4,2,1}, {5,4,3,1}, {4,1,2,2}, {3,4,2,3} } , multisort({a,b,c,d}, { WALL, ROOMS, DESK, CHAIR})) -- test_equal("multi sort 2", { {4,1,2,2}, {3,4,2,1}, {3,4,2,3}, {5,4,3,1} } , multisort({a,b,c,d}, { ROOMS,DESK, CHAIR})) -- test_equal("multi sort 3", { {3,4,2,1}, {3,4,2,3}, {4,1,2,2}, {5,4,3,1} } , multisort({a,b,c,d}, { CHAIR, DESK, ROOMS, WALL}))