On Thursday, October 21, 2021 at 11:26:16 AM UTC+2 gneuner2 wrote: > > On 10/20/2021 5:53 PM, unlimitedscolobb wrote: > > I have two main use cases for producing an ordered list from a hash table: > > 1. A canonical way to pretty print a hash table: In my projects, I carry > around and print out hash tables a lot, so I like the elements to appear in > the same order all the time, whatever that order may be. Luckily, > `hash-map` orders symbols alphabetically and numbers according to the > natural order, so it's perfect for my use. > > > It's fine if it works for you. Just beware hashing on things like lists, > structs, objects, etc. > > Good point indeed, thank you.
> You might look into Laurent Orseau's "text-table" package. Tables are a > great way to print structured output. > > Nice package! These are things which I typically want to do sometimes. At the moment I rely on Org-mode: when evaluating a Racket source code block, I can ask Org-mode to typeset the resulting list as a table, which is often perfect for my purposes. > > 2. Testing the contents of a mutable hash table: The only way I found to > that is to convert the hash table to an ordered list and compared it to the > test list. This is clearly not the most efficient use of a hash table, but > I can totally go with that, since it's about testing and not the actual > performance. > > Of course, I am totally open to learning better ways of doing these things! > > > Depends on what you're trying to do. Sometimes changing the data format > IS the best way. That said ... > > Be aware that the code fragments below were just made up as I wrote this > ... they have not been tested and may contain unbalanced parentheses but > they should give you the idea. Nothing here depends on the ordering of > data in the hashes. Also if you prefer "do" loops to "for" loops, you can > use them instead. > > Note also the use of "in-list", "in-hash-pairs","in-mutable-hash-pairs". > Racket "for" loops work with sequences, and although many data types - > including lists and hashes - will implicitly ACT as sequences, explicitly > using the relevant sequence constructors can make your "for" loops run > faster. > > see https://docs.racket-lang.org/reference/sequences.html > > Oh, sequences, of course! I try using them as much as I can in my code because they are so nice, but I just forgot about them in this particular situation :D > > ===================== > > > To see if 2 hashes contain the same set of keys: > > (and (= (hash-count hash1) (hash-count hash2)) > (for/and ([k (in-list (hash-keys hash1))]) > (hash-has-key? hash2 k))) > > There is a function "hash-keys-subset?" that checks if the keys in one > hash are a subset of keys in another hash. It generally will be faster > than an equivalent loop, but it requires that both hashes use the same key > comparison function. > > > To see if 2 hashes contain the same set of (k,v) pairs: > > ; immutable > (for/and ([(k,v) (in-hash-pairs hash1)]) > (equal v (hash-ref hash2 k fail)) > > ; mutable > (for/and ([(k,v) (in-mutable-hash-pairs hash1)]) > (equal v (hash-ref hash2 k fail)) > > > > Figuring out the difference between one hash vs another is a bit harder, > but a loop similar to the equality check works for this also: > > (for/list ([(k,v) (in-{mutable-}hash-pairs hash1)] > #:unless (equal v (hash-ref hash2 k fail))) > (cons k v)) > > Note that the ordering matters - the loop finds things that are in hash1 > but not in hash2. Also instead of creating a list of what's missing, you > could create another hash: > > ; create immutable hash > (for/hash ([(k,v) (in-{mutable-}hash-pairs hash1)] > #:unless (equal v (hash-ref hash2 k fail))) > (values k v)) > > ; update a mutable hash > (for ([(k,v) (in-{mutable-}hash-pairs hash1)] > #:unless (equal v (hash-ref hash2 k fail))) > (hash-set! result k v)) > > Unfortunately, there is no variant of "for" that creates mutable hashes. > But the general form works for anything. > > > > Obviously there is a theme here. <grin> > > You are free to mix and match things: if your test data already is in > lists, you can use the lists directly - either as the source sequences or > as the lookup targets (since it's only a test, searching lists with > "member" et al shouldn't matter <wink>). > > Thank you for all these examples George! Which makes me wonder: why is there not a hash table comparison function which would be built like one of your suggestions? I'd typically expect such a comparison function to be part of a hash table library. Another opportunity for contributions I guess. - Sergiu Hope this helps, > George > > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/942517a3-3f56-42cb-8dbd-a902364b1cd1n%40googlegroups.com.

