| Scilab Bag Of Tricks: The Scilab-2.5 IAQ (Infrequently Asked Questions) | ||
|---|---|---|
| Prev | Chapter 9. Longer Examples | Next |
The function listdiff returns the differences of two vectors in the style of the diff(1) command. It is a funny example of doing something completely non-numerical with Scilab.
function diff = listdiff(lst1, lst2, equ)
// implement a diff(1) like function for vectors.
// The caller can supply a bool equ(x, y) function
// that will be used in all comparisions, otherwise
// operator "==" is used.
//
// RETURN VALUE
// 2-column vector describing the differences.
// Column 1 contains the element and column 2
// the element's index. A "+" in front of the
// index means: "Extra element in lst2", a "-"
// means missing element in lst1.
[nl, nr] = argn(0);
select nr
case 0 then
error("Too few arguments. Got 0, require 2 or 3.");
case 1 then
error("Too few arguments. Got 1, require 2 or 3.");
case 2 then
deff('b = equ(s1, s2)', 'b = s1 == s2');
case 3 then
// caller supplied equ()
if type(equ) ~= 13 then
error("Function expected, got a " + typeof(equ) + ".");
end
else
error("Too many arguments. Got " + string(nr) + " require 2 or 3.");
end
if type(lst1) ~= 1 & type(lst2) ~= 1 then
// none of the lists is empty
if type(lst1) ~= type(lst2) then
error("Both lists must be of the same type, or be empty.");
end
end
fuzz = 10;
diff = [];
n1 = size(lst1, 1);
n2 = size(lst2, 1);
// special cases
if n1 == 0 & n2 == 0, return, end
if n1 == 0 then
p = 1 : n2;
diff = [lst2, "+" + string(p')];
return;
end
if n2 == 0 then
p = 1 : n1;
diff = [lst1, string(-p')];
return;
end
// general case (neither list is empty)
i = 1;
j = 1;
while i <= n1 & j <= n2
while i <= n1 & j <= n2
if ~equ(lst1(i), lst2(j)), break, end
i = i + 1;
j = j + 1;
end
if i >= n1 | j >= n2, break, end
icurs = i;
while icurs <= min(n1, i+fuzz)
if equ(lst1(icurs), lst2(j)), break, end
icurs = icurs + 1;
end
if icurs <= n1 then
if equ(lst1(icurs), lst2(j)) then
// record element(s) missing from lst1
for p = i : icurs-1
this_diff = [lst1(p), string(-p)];
diff = [diff; this_diff];
end
// re-sync
i = icurs;
end
end
jcurs = j;
while jcurs <= min(n2, j+fuzz)
if equ(lst1(i), lst2(jcurs)), break, end
jcurs = jcurs + 1;
end
if jcurs <= n2 then
if equ(lst1(i), lst2(jcurs)) then
// record extra element(s) in lst2
for p = j : jcurs-1
this_diff = [lst2(p), "+" + string(p)];
diff = [diff; this_diff];
end
// re-sync
j = jcurs;
end
end
end