From 0757a921ab7db0f15ea703b5f5b185fa5a035ba6 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 13 Feb 2019 00:51:53 -0800 Subject: hash-symdiff: new function. * hash.c (hash_symdiff): New function. (hash_init): hash-symdiff intrinsic registered. * hash.h (hash_symdiff): Declared. * txr.1: Documented. --- hash.c | 35 +++++++++++++++++++++++++++++++++++ hash.h | 1 + txr.1 | 22 +++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/hash.c b/hash.c index 4242fd58..272e1e2f 100644 --- a/hash.c +++ b/hash.c @@ -1418,6 +1418,40 @@ val hash_diff(val hash1, val hash2) } } +val hash_symdiff(val hash1, val hash2) +{ + val self = lit("hash-symdiff"); + struct hash *h1 = coerce(struct hash *, cobj_handle(self, hash1, hash_s)); + struct hash *h2 = coerce(struct hash *, cobj_handle(self, hash2, hash_s)); + + if (h1->hops != h2->hops) + uw_throwf(error_s, lit("~a: ~s and ~a are incompatible hashes"), + self, hash1, hash2, nao); + + { + val hout = make_similar_hash(hash1); + val hiter, entry; + + for (hiter = hash_begin(hash1), entry = hash_next(hiter); + entry; + entry = hash_next(hiter)) + { + if (!gethash_e(self, hash2, car(entry))) + sethash(hout, car(entry), cdr(entry)); + } + + for (hiter = hash_begin(hash2), entry = hash_next(hiter); + entry; + entry = hash_next(hiter)) + { + if (!gethash_e(self, hash1, car(entry))) + sethash(hout, car(entry), cdr(entry)); + } + + return hout; + } +} + val hash_isec(val hash1, val hash2, val join_func) { val self = lit("hash-isec"); @@ -1586,6 +1620,7 @@ void hash_init(void) reg_fun(intern(lit("hash-alist"), user_package), func_n1(hash_alist)); reg_fun(intern(lit("hash-uni"), user_package), func_n3o(hash_uni, 2)); reg_fun(intern(lit("hash-diff"), user_package), func_n2(hash_diff)); + reg_fun(intern(lit("hash-symdiff"), user_package), func_n2(hash_symdiff)); reg_fun(intern(lit("hash-isec"), user_package), func_n3o(hash_isec, 2)); reg_fun(intern(lit("hash-subset"), user_package), func_n2(hash_subset)); reg_fun(intern(lit("hash-proper-subset"), user_package), func_n2(hash_proper_subset)); diff --git a/hash.h b/hash.h index df2ca0b3..6b65daf0 100644 --- a/hash.h +++ b/hash.h @@ -65,6 +65,7 @@ val hash_pairs(val hash); val hash_alist(val hash); val hash_uni(val hash1, val hash2, val join_func); val hash_diff(val hash1, val hash2); +val hash_symdiff(val hash1, val hash2); val hash_isec(val hash1, val hash2, val join_func); val hash_subset(val hash1, val hash2); val hash_proper_subset(val hash1, val hash2); diff --git a/txr.1 b/txr.1 index f4242042..7118b588 100644 --- a/txr.1 +++ b/txr.1 @@ -41549,10 +41549,11 @@ dohash early using or .codn (return) . -.coNP Functions @, hash-uni @ hash-diff and @ hash-isec +.coNP Functions @, hash-uni @, hash-diff @ hash-symdiff and @ hash-isec .synb .mets (hash-uni < hash1 < hash2 <> [ join-func ]) .mets (hash-diff < hash1 << hash2 ) +.mets (hash-symdiff < hash1 << hash2 ) .mets (hash-isec < hash1 < hash2 <> [ join-func ]) .syne .desc @@ -41615,6 +41616,25 @@ in .code hash2 are deleted. +The +.code hash-symdiff +function performs a symmetric difference. A new hash is returned which +contains all of the keys from +.meta hash1 +that are not in +.meta hash2 +and +.IR "vice versa" : +all of the keys from +.meta hash2 +that are not in +.metn hash1 . +The keys carry their corresponding values from +.meta hash1 +and +.metn hash2 , +respectively. + The .code hash-isec function performs a set intersection. The resulting hash contains -- cgit v1.2.3