如何计算不同字符的出现并将所有字符作为表格返回

时间:2019-05-15 17:41:29

标签: lisp common-lisp

这是确切的问题:

COUNT-BASES计算每种类型的碱基数     单链或双链DNA并返回结果     作为表格。

(COUNT-BASES '((G C) (A T) (T A) (C G))) should return
((A 2) (T 2) (G 2) (C 2))
(COUNT-BASES '(A G T A C T C T)) should return
((A 2) (T 3) (G 1) (C 2)).

我编写了一个函数my-count,该函数返回一个字符的出现,但不知道如何将其应用于所有4个字母(A T G C)并作为表返回。

;returns the count of a base (a) from a list (L)
(defun my-count (a L)
  (cond ((null L) 0)
        ((equal a (car L)) (+ 1 (my-count a (cdr L))))
        (t (my-count a (cdr L)))))

2 个答案:

答案 0 :(得分:1)

我将首先处理平整的箱子(单股,即一连串的底座)。遍历列表并将每个基数计入哈希表:

(defun count-bases (dna)
  (let ((counts (make-hash-table)))
    (dolist (base dna counts)
      (incf (gethash base counts 0)))))

现在,它可能是双链的,因此每个元素都不是碱基,而是碱基列表。但是我们已经知道如何处理碱基列表。为了计入单个表,可以将其传递给递归调用:

(defun count-bases (dna &optional (counts (make-hash-table)))
  (dolist (base-or-pair dna counts)
    (if (symbolp base-or-pair)
        (incf (gethash base-or-pair counts 0))
        (count-bases base-or-pair counts))))

答案 1 :(得分:1)

该代码的纯命令性版本可能如下:

(defun count-bases (bases)
  (let ((atgc (vector 0 0 0 0)))
    (dolist (dna bases (map 'list #'list #(a t g c) atgc))
      (dolist (base (if (listp dna) dna (list dna)))
        (incf (svref atgc (position base #(a t g c))))))))
  1. 创建一个由4个元素组成的向量,用于存储所有碱基的计数器。
  2. 遍历列表中的所有条目,并遍历每个条目中的所有基数:通常是用alexandria:ensure-list完成的,但这里是用纯文字编写的。
  3. 在文字向量#(a t g c)(符号向量)中找到每个碱基的位置。使用返回的位置递增关联的计数器。
  4. 最后(最后一个格式为DOLIST),以期望的格式构建返回值:

    通过#(a t g c)和计数器向量atgc上的

    MAP,通过将函数'list应用于从两个序列中获取的每对元素来构建#'list :例如,第一次迭代访问a和基础a的计数器,并在其上调用#'list,从而构建(a ...),其中...是实际值