Scheme 在Racket中查找列表中出现次数最多的元素

Scheme 在Racket中查找列表中出现次数最多的元素,scheme,racket,Scheme,Racket,如何找到列表中出现次数最多的元素 如果有更多相同编号的,则可以返回任何编号 例如,对于列表“1 3 4 2 2”,函数可以返回2或3 我想我可以计算每个元素出现的次数,然后选择最大值,但这似乎有点低效。有没有更好的方法,或者更好的内置函数?如果在计数前对列表进行排序,效率会稍微提高一些。然后,具有特定值的所有元素将一起出现在列表中。然后,当您计算完示例列表中的2后,您就不必再保留1的数量,因为您的函数已经知道1不是出现次数最多的元素。使用 !r6rs 输入rnrs基 srfi:69 定义最大发生

如何找到列表中出现次数最多的元素

如果有更多相同编号的,则可以返回任何编号

例如,对于列表“1 3 4 2 2”,函数可以返回2或3


我想我可以计算每个元素出现的次数,然后选择最大值,但这似乎有点低效。有没有更好的方法,或者更好的内置函数?

如果在计数前对列表进行排序,效率会稍微提高一些。然后,具有特定值的所有元素将一起出现在列表中。然后,当您计算完示例列表中的2后,您就不必再保留1的数量,因为您的函数已经知道1不是出现次数最多的元素。

使用

!r6rs 输入rnrs基 srfi:69 定义最大发生lst 定义哈希表生成哈希表 定义零λ0 让循环lst lst mfreq 0 mcur f 如果为空?lst 麦库尔 让*元素car lst freq+1哈希表ref哈希元素为零 哈希表集!散列元素频率 如果>频率mfreq 循环cdr lst freq元素 循环cdr lst mfreq mcur A!racket版本与之非常相似,只是惯用版本会选择不可变的哈希表

!球拍 定义最大发生lst 让循环散列成为不可变散列lst lst mfreq 0 mcur f 如果为空?lst 麦库尔 让*元素car lst freq add1散列引用散列元素0 如果>频率mfreq 循环哈希集哈希元素频率 cdr lst 频率 要素 循环哈希集哈希元素频率 cdr lst mfreq 麦库尔
如果您在列表中遇到性能问题,我想您会看到这两个列表中的任何一个都有很大的改进。在中更改为可变哈希表!racket会使速度加倍,但我怀疑您是否需要它。

这里有一个基于racket哈希表的解决方案

#lang racket
(define (most-frequent-element xs)
  (define ht (make-hash))
  (for ([x xs]) (hash-update! ht x add1 0))
  (for/fold ([max-x #f] [max-count 0]) ([(x c) ht])
    (if (> c max-count)
        (values x c)
        (values max-x max-count))))
例如:

> (most-frequent-element '(a b c c d a a b c a))
'a
4
> (most-frequent-element '(a b c c d a a b c a))
'(a . 4)
下面是一个使用argmax的解决方案。不幸的是,它需要 从哈希表到列表的转换

#lang racket

(define (most-frequent-element xs)
  (define ht (make-hash))
  (for ([x xs]) (hash-update! ht x add1 0))
  (argmax (λ (x) (hash-ref ht x 0)) 
          (hash->list ht)))
例如:

> (most-frequent-element '(a b c c d a a b c a))
'a
4
> (most-frequent-element '(a b c c d a a b c a))
'(a . 4)

如果列表中的元素是数字吗?@soegaard我想只要它们都是eqv就没什么关系了?-可比。我喜欢这个。虽然从概念上讲for/fold可以简化为argmax cdr hash->list ht,但这至少要慢一些。我添加了一个使用argmax的版本。我对第一个版本做了一些改进。[x c ht]将迭代键x及其值c和计数。