【问题标题】:How to map over values of a hash table (racket)如何映射哈希表的值(球拍)
【发布时间】:2013-01-15 22:28:08
【问题描述】:

我想在哈希表中的值上映射一个函数,如下所示:

(hash-map add1 (hash "apple" 1 "pear" 2))
=> #hash(("apple" . 2) ("pear" . 3))

是否有库函数可以做到这一点?最好有一个也可以处理不可变哈希表。

我查看了PlaneT,但没有看到任何东西。

现在,如果这真的不存在,我会继续写它。把这个带入球拍的礼仪是什么?我只是在 github 上 fork 并将其添加到标准库(和文档!)并提交拉取请求?还是我应该先把它变成一个planeT,然后再要求它搬进来?我想帮忙,但我只是不知道什么是“正确”的方法。

【问题讨论】:

    标签: scheme hashtable racket


    【解决方案1】:

    有一个哈希映射,但它返回一个列表 [1]

    您必须编写自己的 hash-map 才能完全按照您的意愿行事。

    #lang racket
    
    (define (new-hash-map f h)
      (make-immutable-hash (hash-map h (λ (k v) (cons k (f v))))))
    
    (new-hash-map add1 (hash "apple" 1 "pear" 2))
    
    ; => '#hash(("pear" . 3) ("apple" . 2))
    

    您可能感兴趣的另一种形式是 for/hash [2]:

    #lang racket
    
    (define (new-hash-map2 f h)
      (for/hash ([(k v) (in-hash h)]) (values k (f v))))
    
    (new-hash-map2 add1 (hash "apple" 1 "pear" 2))
    
    ; => '#hash(("pear" . 3) ("apple" . 2))
    

    如果您认为 Racket 应该包含此功能,欢迎使用补丁!最好的贡献方式是在 github 上 fork 并提交 pull request。

    【讨论】:

    • 来自 irc 频道的 stamourv 也推荐了 for/hash,这就是我最终使用的。非常感谢。
    • @TheoBelaire 用了什么样的理由来推荐它?就目前而言,我认为这两种变体都没有任何优势。
    • 那是很久以前的事了,我不记得了。我认为它不必构造一个列表然后构造一个哈希表,但这可能是错误的。
    【解决方案2】:

    您可以使用in-hash-values 遍历哈希表的值,并使用常规for loops 映射它们。函数in-hash-values 接受一个散列并返回一个值序列,然后可以使用for 循环对其进行遍历。

    例子:

    (for/list ([elt (in-hash-values (hash "apple" 1 "pear" 2))])
      (add1 elt))
    

    同样,你可以使用sequence-map,虽然你得到的是另一个序列而不是列表:

    (sequence-map add1 (in-hash-values (hash "apple" 1 "pear" 2)))
    

    【讨论】:

      【解决方案3】:

      在 Racket 中,您可以使用hash-map 高阶过程,该过程通常返回一个列表,其中包含应用作为参数接收的过程所产生的值,但它可以适用于就地修改地图。例如:

      (define h (make-hash))
      (hash-set! h "apple" 1)
      (hash-set! h "pear" 2)
      
      h
      => '#hash(("pear" . 2) ("apple" . 1))
      

      诀窍是传递具有适当功能的lambda

      (hash-map h (lambda (key value)
                    (let ((newval (add1 value)))
                      (hash-set! h key newval)
                      newval)))
      
      h
      => '#hash(("pear" . 3) ("apple" . 2))
      

      对于更通用的解决方案,请尝试以下实现:

      (define (mutable-hash-map! hash proc)
        (hash-map hash (lambda (key value)
                         (hash-set! hash key (proc value))))
        (void))
      

      【讨论】:

        【解决方案4】:

        由于 hash-map 创建了一个此处不需要的列表,我宁愿使用 hash-for-each

        (define (hash-update-all! h func)
          (hash-for-each
            h
            (lambda (k v) (hash-set! h k (func v)))))
        
        (define table (make-hash '((a . 1) (b . 2) (c . 3))))
        
        (hash-update-all! table (curry * 100))
        
        table
        
         ==> '#hash((c . 300) (a . 100) (b . 200))
        

        编辑:我忘了 for 可以处理哈希表:

        (define (hash-update-all! h func)
          (for ([(k v) h])   (hash-set! h k (func v))))
        
        (hash-update-all! table (curryr / 10))
        
        table
        
         ==> '#hash((c . 30) (a . 10) (b . 20))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-04
          • 1970-01-01
          • 2013-12-18
          相关资源
          最近更新 更多