所以我有一个元素列表的示例,像这样:
现在我想从这个样本中制作一个排名。
结果应该如下所示:
因为` scan` 函数将创建一个哈希表,其中包含唯一键和该键的重复次数(如果它捕获了一个未被索引的键,则会为该新键创建一个新位置,从0开始计数)。
然后我想对该哈希表进行排序,因为它是未排序的:
扫描功能将有一些不同:
(define A (list 'a 'c 'd 'e 'f 'e 'a))
现在我想从这个样本中制作一个排名。
(define (scan lst)
(foldl (lambda (element a-hash) (hash-update a-hash element add1 0))
(hash)
lst))
结果应该如下所示:
> #(('a . 2) ('f . 1) ('e . 2) ....)
因为` scan` 函数将创建一个哈希表,其中包含唯一键和该键的重复次数(如果它捕获了一个未被索引的键,则会为该新键创建一个新位置,从0开始计数)。
然后我想对该哈希表进行排序,因为它是未排序的:
(define (rank A)
(define ranking (scan A))
(sort ranking > #:key cdr)))
因此,结果应如下所示:
#(('a . 2) ('e . 2) ('f . 1) ...)
现在我想截断哈希表并在n = 1的阈值处将底部丢弃(仅取具有超过2个重复项的元素)。
(define (truncate lst n)
(define l (length lst))
(define how-many-to-take
(for/list
([i l]
#:when (> (cdr (list-ref lst i))
n))
i))
(take lst (length how-many-to-take)))
因此,结果可能如下:
(('a . 2) ('e . 2))
然而,在大规模情况下,这个过程不是很高效,它需要太长时间。您有任何建议来提高性能吗?
非常感谢,
第二部分:
我有这个数据结构:
(automaton x
(vector (state y (vector a b c))
(state y (vector a b c)) ...))
然后我随机生成了1000个个体。接着,我使用上述功能进行扫描和排名。如果我只是按原样扫描它们,那么已经需要很长时间。如果我尝试将它们压缩成一个列表,如下所示:
(list x y a b c y a b c...)
如果需要,这将需要更多的时间。这是“flatten”函数:
(define (flatten-au au)
(match-define (automaton x states) au)
(define l (vector-length states))
(define body
(for/list ([i (in-range l)])
(match-define (state y z) (vector-ref states i))
(list y (vector->list z))))
(flatten (list x body)))
扫描功能将有一些不同:
(define (scan population)
(foldl (lambda (auto a-hash) (hash-update a-hash (flatten-automaton auto) add1 0))
(hash)
population))
for/hash
会遍历整个列表。不同之处在于,你原来的解决方案遍历了整个列表,并且对于每个元素,都遍历了整个列表!(实际上,它只遍历了部分列表,但让我们不要陷入渐近复杂度的讨论中)。针对你的第二个问题:你的列表有多长,扫描需要多长时间? - John Clements