summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hash.c35
-rw-r--r--hash.h1
-rw-r--r--txr.122
3 files changed, 57 insertions, 1 deletions
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
@@ -41616,6 +41617,25 @@ in
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
only those keys which occur both in