函数返回地图列表,同时迭代字符串,kmer计数
我正在创建一个用Scala编写的k-mer频率计数器(类似于Hadoop中的字数)。我对Scala相当陌生,但我有一些编程经验。函数返回地图列表,同时迭代字符串,kmer计数
输入是一个包含基因序列的文本文件,我的任务是获取每个k-mer的频率,其中k
是序列的某个指定长度。
因此,序列AGCTTTC
具有三个5聚体(AGCTT,GCTTT,CTTTC)
我已经通过输入解析并创造了巨大的字符串这是整个序列,新线甩开作为一行序列末尾的k-mer计数仍应与下一行序列的开始形成k-mer。
现在我想写这将产生地图List[Map[String, Int]]
的列表,它应该很容易使用Scala的groupBy
函数来获得共同的k聚体
import scala.io.Source
object Main {
def main(args: Array[String]) {
// Get all of the lines from the input file
val input = Source.fromFile("input.txt").getLines.toArray
// Create one huge string which contains all the lines but the first
val lines = input.tail.mkString.replace("\n","")
val mappedKmers: List[Map[String,Int]] = getMappedKmers(5, lines)
}
def getMappedKmers(k: Int, seq: String): List[Map[String, Int]] = {
for (i <- 0 until seq.length - k) {
Map(seq.substring(i, i+k), 1) // Map the k-mer to a count of 1
}
}
}
夫妇的计数功能问题:
- 如何创建/生成
List[Map[String,Int]]
? - 你会怎么做?
任何帮助和/或建议绝对赞赏!
你非常接近 - 你的代码有三个相当小的问题。
第一个是for (i <- whatever) foo(i)
是语法糖whatever.foreach(i => foo(i))
,这意味着你实际上没有对whatever
的内容做任何事情。你想要的是for (i <- whatever) yield foo(i)
,这是whatever.map(i => foo(i))
的糖,并返回已转换的集合。
的第二个问题是,0 until seq.length - k
是Range
,不是List
,因此,即使一旦你添加了yield
,结果仍然不会与声明的返回类型排队。
第三个问题是Map(k, v)
试图创建一个包含两个键值对的地图k
和v
。您需要Map(k -> v)
或Map((k, v))
,其中任何一个都明确表示您拥有单个参数对。
所以下面应该工作:
def getMappedKmers(k: Int, seq: String): IndexedSeq[Map[String, Int]] = {
for (i <- 0 until seq.length - k) yield {
Map(seq.substring(i, i + k) -> 1) // Map the k-mer to a count of 1
}
}
你也可以的范围或整个结果转换到一个列表与.toList
如果你愿意在最后名单。
值得一提的,顺便说一句,上Seq
的sliding
方法不正是你想要什么:
scala> "AGCTTTC".sliding(5).foreach(println)
AGCTT
GCTTT
CTTTC
,我肯定会建议像"AGCTTTC".sliding(5).toList.groupBy(identity)
真正的代码。
为什么你用'1'来映射每一个kmer?它看起来只能是一个kmer,因此返回的类型可以只是'List [String]'。所以我建议的代码就是'seq sliding k toList'。 – 2014-10-06 02:27:37
好点,我实际上只是在一分钟前试图做这样的事情。 '1'在那里,因为我试图调整这一段代码以适应字数在hadoop MapReduce作业中的工作方式,其中每个键映射值为1,并且reduce函数累积每个键的总数(此处为kmer案件) – Joe 2014-10-06 02:33:09