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.

Reply via email to