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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/942517a3-3f56-42cb-8dbd-a902364b1cd1n%40googlegroups.com.

Reply via email to