【问题标题】:How do I convert a string to a hash ( key: character, value: list of the index of the character ) in Racket?如何在 Racket 中将字符串转换为散列(键:字符,值:字符索引列表)?
【发布时间】:2022-11-18 17:25:57
【问题描述】:

我想将一个字符串转换为一个哈希表,其键是字符串中的字符,值是该字符在字符串中的索引列表。有什么优雅的方法可以做到这一点吗?

例如:

String: "abcaad"

Hash table: { a: [0 3 4] , b: [1] , c: [2] , d: [5] }

我尝试用 hash-set! 编写一个并从末尾迭代字符串以避免 append 比在开始时插入慢。但我希望会有一些更优雅的方式(如果我能得到一个向量而不是每个哈希值的列表更好):

(define (s->hash s)
  (define h (make-hash))
  (for ([c (in-string s (sub1 (string-length s)) -1 -1)]
        [i (in-range (sub1 (string-length s)) -1 -1)])
    (hash-set! h c (cons i (hash-ref h c empty))))
  h)

【问题讨论】:

    标签: lisp racket


    【解决方案1】:

    我们可以使用in-indexed 来稍微简化解决方案:

    (define (s->hash s)
      (define h (make-hash))
      (for ([(c i) (in-indexed s)])
        (hash-set! h c (cons i (hash-ref h c empty))))
      h)
    

    或者我们可以编写函数式编程风格的解决方案,通过组合现有的内置过程并使用 hash-update 摆脱 hash-set! 变异操作,这在 Scheme 中编程时有点不受欢迎:

    (define (s->hash s)
      (for/fold ((ht #hash()))
                (((key index) (in-indexed s)))
        (hash-update ht
                     key
                     (lambda (acc) (cons index acc))
                     '())))
    

    两种解决方案都以相反的顺序返回索引列表,使用 cons 比使用 append 连接列表末尾的索引更有效。如果这是一个问题,您可以稍后反转列表,如下所示,或者使用 append 而不是 cons(出于性能原因不鼓励。)

    (define (reverse-index-lists ht)
      (foldl (lambda (key acc) (hash-update acc key reverse))
             ht
             (hash-keys ht)))
    

    使用 vector 不适合解决这个问题,因为我们事先不知道每个向量的大小(在 Scheme 中载体更像是数组在其他编程语言中,在无法调整大小的意义上)。让我们看看它的实际效果:

    (s->hash "abcaad")
    '#hash((# . (4 3 0)) (# . (1)) (#c . (2)) (#d . (5)))
    
    (reverse-index-lists (s->hash "abcaad"))
    '#hash((# . (0 3 4)) (# . (1)) (#c . (2)) (#d . (5)))
    

    【讨论】:

    • 有一些可生长的载体可以通过几个不同的包(一个来自你的包)使用。如果我有时间,我会在今天晚些时候尝试提出一个涵盖它们的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 2022-10-15
    • 2023-02-23
    • 2012-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多