diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-10-12 21:10:40 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-10-12 21:10:40 -0700 |
commit | 1c11fe21f49559fbb0f2ee8fa9b702338207e7a0 (patch) | |
tree | d50ac6976f167da9d3b0bd3150ee81522b332209 | |
parent | 03699dd7d47cbf95552bed02e5c37f078528a3b2 (diff) | |
download | txr-1c11fe21f49559fbb0f2ee8fa9b702338207e7a0.tar.gz txr-1c11fe21f49559fbb0f2ee8fa9b702338207e7a0.tar.bz2 txr-1c11fe21f49559fbb0f2ee8fa9b702338207e7a0.zip |
find-max and find-min support hashes.
* lib.c (find_max): Restructured to implement separately
for vectors and lists. Support hash tables.
* txr.1: Document find-min and find-max for hashes.
-rw-r--r-- | lib.c | 68 | ||||
-rw-r--r-- | txr.1 | 23 |
2 files changed, 76 insertions, 15 deletions
@@ -7544,8 +7544,6 @@ val rfind(val item, val list, val testfun, val keyfun) val find_max(val seq, val testfun, val keyfun) { - val maxkey; - val maxelt; seq = nullify(seq); @@ -7555,21 +7553,65 @@ val find_max(val seq, val testfun, val keyfun) testfun = default_arg(testfun, greater_f); keyfun = default_arg(keyfun, identity_f); - maxelt = car(seq); - maxkey = funcall1(keyfun, maxelt); + switch (type(seq)) { + case COBJ: + if (seq->co.cls == hash_s) { + val hiter = hash_begin(seq); + val cell = hash_next(hiter); + val maxelt = cell; + val maxkey = if2(cell, funcall1(keyfun, cell)); + + while (cell && (cell = hash_next(hiter))) { + val key = funcall1(keyfun, cell); + if (funcall2(testfun, key, maxkey)) { + maxkey = key; + maxelt = cell; + } + } - gc_hint(seq); + return maxelt; + } + /* fallthrough */ + case CONS: + case LCONS: + { + val maxelt = car(seq); + val maxkey = funcall1(keyfun, maxelt); - for (seq = cdr(seq); seq; seq = cdr(seq)) { - val elt = car(seq); - val key = funcall1(keyfun, elt); - if (funcall2(testfun, key, maxkey)) { - maxkey = key; - maxelt = elt; + gc_hint(seq); + + for (seq = cdr(seq); seq; seq = cdr(seq)) { + val elt = car(seq); + val key = funcall1(keyfun, elt); + if (funcall2(testfun, key, maxkey)) { + maxkey = key; + maxelt = elt; + } + } + return maxelt; } - } + case STR: + case LSTR: + case VEC: + { + val maxelt = ref(seq, zero); + val maxkey = funcall1(keyfun, maxelt); + val len = length(seq); + val i; - return maxelt; + for (i = zero; lt(i, len); i = succ(i)) { + val elt = ref(seq, i); + val key = funcall1(keyfun, elt); + if (funcall2(testfun, key, maxkey)) { + maxkey = key; + maxelt = elt; + } + } + return maxelt; + } + default: + uw_throwf(error_s, lit("find-max: unsupporte object ~s is a literal"), seq, nao); + } } val find_min(val seq, val testfun, val keyfun) @@ -23877,8 +23877,8 @@ the leftmost. .coNP Functions @ find-max and @ find-min .synb -.mets (find-max < sequence >> [ testfun <> [ keyfun ]]) -.mets (find-min < sequence >> [ testfun <> [ keyfun ]]) +.mets (find-max >> { sequence | << hash } >> [ testfun <> [ keyfun ]]) +.mets (find-min >> { sequence | << hash } >> [ testfun <> [ keyfun ]]) .syne .desc The @@ -23940,6 +23940,25 @@ is passed through this one-argument function, and the resulting value is used in its place for the purposes of the comparison. However, the original element is returned. +A hash table may be specified instead of a sequence. +The +.meta hash +is treated as if it were a sequence of hash key and hash +value pairs represented as cons cells, the +.code car +slots of which are the hash keys, and the +.code cdr +of which are the hash values. If the caller doesn't specify a +.meta keyfun +then these cells are taken as their keys. To find the hash +table's key-value cell with the maximum key, the +.code car +function can be specified as +.metn keyfun . +To find the entry holding the maximum value, the +.code cdr +function can be specified. + .coNP Function @ set-diff .synb .mets (set-diff < seq1 < seq2 >> [ testfun <> [ keyfun ]]) |