3 回答

TA貢獻1862條經驗 獲得超6個贊
您的問題不是很具體,關于所計算的內容。我假設您要創建某種形式的元素頻率表。有幾種方法可以解決此問題。(如果您使用的是Racket,請向下滾動至底部以找到我的首選解決方案。)
便攜式,純功能,但冗長且緩慢
此方法使用關聯列表(alist)來保存元素及其計數。對于傳入列表中的每個項目,它將在列表中查找該項目,并遞增其存在的值;如果不存在,則將其初始化為1。
(define (bagify lst)
(define (exclude alist key)
(fold (lambda (ass result)
(if (equal? (car ass) key)
result
(cons ass result)))
'() alist))
(fold (lambda (key bag)
(cond ((assoc key bag)
=> (lambda (old)
(let ((new (cons key (+ (cdr old) 1))))
(cons new (exclude bag key)))))
(else (let ((new (cons key 1)))
(cons new bag)))))
'() lst))
遞增是有趣的部分。為了實現純功能,我們實際上不能更改alist的任何元素,而是必須排除要更改的關聯,然后將該關聯(帶有新值)添加到結果中。例如,如果您具有以下列表:
((foo . 1) (bar . 2) (baz . 2))
并想在baz的值上加1 ,則創建一個新的列表,該列表不包括baz:
((foo . 1) (bar . 2))
然后添加baz的新值:
((baz . 3) (foo . 1) (bar . 2))
第二步是exclude函數的功能,并且可能是函數中最復雜的部分。
便攜式,簡潔,快速但無功能
一種更直接的方法是使用哈希表(來自SRFI 69),然后針對列表中的每個元素逐一對其進行更新。由于我們直接更新哈希表,因此它不是純粹的功能。
(define (bagify lst)
(let ((ht (make-hash-table)))
(define (process key)
(hash-table-update/default! ht key (lambda (x) (+ x 1)) 0))
(for-each process lst)
(hash-table->alist ht)))
純功能,簡潔,快速但不可攜帶
此方法使用特定于球拍的哈希表(與SRFI 69的哈希表不同),該哈希表確實支持純功能的工作流程。另一個好處是,該版本也是三個版本中最簡潔的版本。
(define (bagify lst)
(foldl (lambda (key ht)
(hash-update ht key add1 0))
#hash() lst))
您甚至可以for對此進行理解:
(define (bagify lst)
(for/fold ((ht #hash()))
((key (in-list lst)))
(hash-update ht key add1 0)))
這比可移植SRFI 69哈希庫的缺點更能說明問題,而不是Scheme的任何特定失敗都無法完成純功能任務。使用正確的庫,可以輕松且功能上地實現此任務。

TA貢獻1847條經驗 獲得超11個贊
在像Scheme這樣的函數式編程語言中,您必須有所不同,并利用構造列表的方式。無需通過增加索引來遍歷列表,而是遞歸地遍歷列表。您可以使用car
(單個元素)刪除列表的頭部,可以使用cdr
(列表本身)獲取列表的尾部,并且可以將頭部和其尾部粘合在一起cons
。您的功能概述如下:
您必須“遞歸”要搜索的元素以及該函數每次調用的當前計數
如果您擊中空白列表,則列表已完成,您可以輸出結果
如果列表中的汽車等于您要查找的元素,請使用列表的cdr和計數器+ 1遞歸調用該函數
如果不是,請使用列表的cdr和與以前相同的計數器值遞歸調用該函數
- 3 回答
- 0 關注
- 694 瀏覽
添加回答
舉報