Improved compare_vals() and compare_lists() for heterogenous types.

This commit is contained in:
Revar Desmera 2019-06-24 15:31:59 -07:00
parent 94c2378136
commit 56b41b487b
2 changed files with 97 additions and 48 deletions

View file

@ -366,49 +366,49 @@ function determinant(M) =
// Section: Comparisons and Logic
function _type_num(x) =
is_undef(x)? 0 :
is_bool(x)? 1 :
is_num(x)? 2 :
is_string(x)? 3 :
is_list(x)? 4 : 5;
// Function: compare_vals()
// Usage:
// compare_vals(a, b);
// Description:
// Compares two values. Lists are compared recursively.
// Results are undefined if the two values are not of similar types.
// If types are not the same, then undef < bool < num < str < list < range.
// Arguments:
// a = First value to compare.
// b = Second value to compare.
function compare_vals(a, b) =
(a==b)? 0 :
(a==undef)? -1 :
(b==undef)? 1 :
((a==[] || a=="" || a[0]!=undef) && (b==[] || b=="" || b[0]!=undef))? (
compare_lists(a, b)
) : (a<b)? -1 :
(a>b)? 1 : 0;
let(t1=_type_num(a), t2=_type_num(b)) (t1!=t2)? (t1-t2) :
is_list(a)? compare_lists(a,b) :
(a<b)? -1 : (a>b)? 1 : 0;
// Function: compare_lists()
// Usage:
// compare_lists(a, b)
// Description:
// Compare contents of two lists.
// Compare contents of two lists using `compare_vals()`.
// Returns <0 if `a`<`b`.
// Returns 0 if `a`==`b`.
// Returns >0 if `a`>`b`.
// Results are undefined if elements are not of similar types.
// Arguments:
// a = First list to compare.
// b = Second list to compare.
function compare_lists(a, b, n=0) =
let(
// This curious construction enables tail recursion optimization.
cmp = (a==b)? 0 :
(len(a)<=n)? -1 :
(len(b)<=n)? 1 :
(a==a[n] || b==b[n])? (
a<b? -1 : a>b? 1 : 0
) : compare_vals(a[n], b[n])
)
(cmp != 0 || a==b)? cmp :
compare_lists(a, b, n+1);
function compare_lists(a, b) =
a==b? 0 : let(
cmps = [
for(i=[0:1:min(len(a),len(b))-1]) let(
cmp = compare_vals(a[i],b[i])
) if(cmp!=0) cmp
]
) cmps==[]? (len(a)-len(b)) : cmps[0];
// Function: any()

View file

@ -282,52 +282,101 @@ test_mean();
module test_compare_vals() {
assert(compare_vals(-10,0) == -1);
assert(compare_vals(10,0) == 1);
assert(compare_vals(-10,0) < 0);
assert(compare_vals(10,0) > 0);
assert(compare_vals(10,10) == 0);
assert(compare_vals("abc","abcd") == -1);
assert(compare_vals("abcd","abc") == 1);
assert(compare_vals("abc","abcd") < 0);
assert(compare_vals("abcd","abc") > 0);
assert(compare_vals("abcd","abcd") == 0);
assert(compare_vals(false,false) == 0);
assert(compare_vals(true,false) == 1);
assert(compare_vals(false,true) == -1);
assert(compare_vals(true,false) > 0);
assert(compare_vals(false,true) < 0);
assert(compare_vals(true,true) == 0);
assert(compare_vals([2,3,4], [2,3,4,5]) == -1);
assert(compare_vals([2,3,4], [2,3,4,5]) < 0);
assert(compare_vals([2,3,4,5], [2,3,4,5]) == 0);
assert(compare_vals([2,3,4,5], [2,3,4]) == 1);
assert(compare_vals([2,3,4,5], [2,3,5,5]) == -1);
assert(compare_vals([[2,3,4,5]], [[2,3,5,5]]) == -1);
assert(compare_vals([2,3,4,5], [2,3,4]) > 0);
assert(compare_vals([2,3,4,5], [2,3,5,5]) < 0);
assert(compare_vals([[2,3,4,5]], [[2,3,5,5]]) < 0);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) == -1);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) == -1);
assert(compare_vals([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) == 1);
assert(compare_vals([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) == 1);
assert(compare_vals([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) == 1);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) == -1);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0);
assert(compare_vals([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0);
assert(compare_vals([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0);
assert(compare_vals([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0);
assert(compare_vals([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0);
assert(compare_vals(undef, undef) == 0);
assert(compare_vals(undef, true) < 0);
assert(compare_vals(undef, 0) < 0);
assert(compare_vals(undef, "foo") < 0);
assert(compare_vals(undef, [2,3,4]) < 0);
assert(compare_vals(undef, [0:3]) < 0);
assert(compare_vals(true, undef) > 0);
assert(compare_vals(true, true) == 0);
assert(compare_vals(true, 0) < 0);
assert(compare_vals(true, "foo") < 0);
assert(compare_vals(true, [2,3,4]) < 0);
assert(compare_vals(true, [0:3]) < 0);
assert(compare_vals(0, undef) > 0);
assert(compare_vals(0, true) > 0);
assert(compare_vals(0, 0) == 0);
assert(compare_vals(0, "foo") < 0);
assert(compare_vals(0, [2,3,4]) < 0);
assert(compare_vals(0, [0:3]) < 0);
assert(compare_vals(1, undef) > 0);
assert(compare_vals(1, true) > 0);
assert(compare_vals(1, 1) == 0);
assert(compare_vals(1, "foo") < 0);
assert(compare_vals(1, [2,3,4]) < 0);
assert(compare_vals(1, [0:3]) < 0);
assert(compare_vals("foo", undef) > 0);
assert(compare_vals("foo", true) > 0);
assert(compare_vals("foo", 1) > 0);
assert(compare_vals("foo", "foo") == 0);
assert(compare_vals("foo", [2,3,4]) < 0);
assert(compare_vals("foo", [0:3]) < 0);
assert(compare_vals([2,3,4], undef) > 0);
assert(compare_vals([2,3,4], true) > 0);
assert(compare_vals([2,3,4], 1) > 0);
assert(compare_vals([2,3,4], "foo") > 0);
assert(compare_vals([2,3,4], [2,3,4]) == 0);
assert(compare_vals([2,3,4], [0:3]) < 0);
assert(compare_vals([0:3], undef) > 0);
assert(compare_vals([0:3], true) > 0);
assert(compare_vals([0:3], 1) > 0);
assert(compare_vals([0:3], "foo") > 0);
assert(compare_vals([0:3], [2,3,4]) > 0);
assert(compare_vals([0:3], [0:3]) == 0);
}
test_compare_vals();
module test_compare_lists() {
assert(compare_lists([2,3,4], [2,3,4,5]) == -1);
assert(compare_lists([2,3,4], [2,3,4,5]) < 0);
assert(compare_lists([2,3,4,5], [2,3,4,5]) == 0);
assert(compare_lists([2,3,4,5], [2,3,4]) == 1);
assert(compare_lists([2,3,4,5], [2,3,5,5]) == -1);
assert(compare_lists([2,3,4,5], [2,3,4]) > 0);
assert(compare_lists([2,3,4,5], [2,3,5,5]) < 0);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5]]) == 0);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) == -1);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) == -1);
assert(compare_lists([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) == 1);
assert(compare_lists([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) == 1);
assert(compare_lists([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) == 1);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) == -1);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4,5], [3,4,5]]) < 0);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,4,5,6]]) < 0);
assert(compare_lists([[2,3,4,5],[3,4,5]], [[2,3,4], [3,4,5]]) > 0);
assert(compare_lists([[2,3,4],[3,4,5,6]], [[2,3,4], [3,4,5]]) > 0);
assert(compare_lists([[2,3,4],[3,5,5]], [[2,3,4], [3,4,5]]) > 0);
assert(compare_lists([[2,3,4],[3,4,5]], [[2,3,4], [3,5,5]]) < 0);
assert(compare_lists("cat", "bat") == 1);
assert(compare_lists(["cat"], ["bat"]) == 1);
assert(compare_lists("cat", "bat") > 0);
assert(compare_lists(["cat"], ["bat"]) > 0);
}
test_compare_lists();