2015-06-10 3 views
1

Я работаю над некоторыми упражнениями для упражнений. Текущий, над которым я работаю, - это упражнение ДНК Scala. Вот мой код и ошибки, которые я получаю:Ошибки понимания Scala

Для справки, ДНК создается экземпляром строки String. Эта ДНК может вызывать подсчет (который учитывает прядь для пропущенного одиночного нуклеотида) и нуклеиновые количества, которые подсчитывают все соответствующие вхождения каждого нуклеотида в нити и возвращают Map[Char,Int].

class DNA(strand:String) { 

    def count(nucleotide:Char): Int = { 
    strand.count(_ == nucleotide) 
    } 

    def nucleotideCounts = (
    for { 
     n <- strand 
     c <- count(n) 
    } yield (n, c) 
).toMap 

} 

Ошибки я получаю являются:

Error:(10, 17) value map is not a member of Int c <- count(n) ^

Error:(12, 5) Cannot prove that Char <:< (T, U). ).toMap ^

Error:(12, 5) not enough arguments for method toMap: (implicit ev: <:<[Char,(T, U)])scala.collection.immutable.Map[T,U]. Unspecified value parameter ev. ).toMap ^

Я совершенно новой для Scala, поэтому любое просветление, почему эти ошибки происходят и предложения по их устранению было бы весьма признателен.

ответ

3

for понимает работу над Traversable's, которые имеют flatMap и map методы, определенные, как указывает сообщение об ошибке.

В вашем случае count возвращает с простым целым числом, поэтому нет необходимости «перебирать» его, просто добавьте его в свой результирующий набор.

for { 
    n <- strand 
} yield (n, count(n)) 

На стороне записки это решение не слишком оптимальное, так как в случае подсчета пряди AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA собирается назвать много раз. Я бы рекомендовал вызова toSet так что вы получите различные Char s только:

for { 
    n <- strand.toSet 
} yield (n, count(n)) 
+0

Удивительно, спасибо! Я знал, что это просто. Scala - это странный язык, который сначала обертывает вашу голову, но это имеет смысл. Я ценю вашу помощь! – lmcphers

+0

Что касается вашего редактирования с установить его равным .toSet, я получаю эту ошибку прямо сейчас: Ошибка: (9, 7) отсутствует параметр типа п <- strand.toSet ^ Почему просят параметра с этим предложением? – lmcphers

+0

Hm, он должен уметь выяснить, что это набор символов 'Char', вы можете попробовать явно ввести его:' .toSet [Char] ' –

0

Раствор трубопровода будет выглядеть так:

def nucleotideCounts() = strand.groupBy(identity).mapValues(_.length) 
+0

Нет, 'n' будет каждый символ' Char' в строке. Попробуйте сами: 'для {n <-" abc "} {println (n)}' –

+0

Попробуйте сделать это с доходностью вместо этого, выход дает всю строку ... –

+0

'for {n <-" abc "} yield {n.toInt}' приводит к: 'Vector (97, 98, 99)' Таким образом, элементы являются отдельными, а не «изначально заданы для всей строки String», как вы сказали. –

1

В соответствии с подходом АКОС, рассмотрите параллельный обход данной цепи (String),

strand.distinct.par.map(n => n -> count(n)) 

Здесь мы используем отчетливый собрать уникальные предметы и построить каждый Map associ в map.

+0

Nice! Мне нравится это краткое решение. Почему в этом случае оптимальное решение будет более оптимальным? Я не реализую много параллелизма в том, что я делаю, поэтому любопытно, как.Команда par работает над вызовом объекта String. Благодаря! – lmcphers

+0

@Imcphers Scala string оснащена упорядоченными методами сбора, поэтому строка использует такие методы сбора. С помощью par мы получаем параллельную версию коллекции, после чего мы можем применять тяжелые вычисления для каждого элемента в коллекции параллельно. Здесь это может оказаться интересным для очень большого подсчета, хотя требуется очень большая коллекция. Большое спасибо за запрос на это :) – elm

+0

Не беспокойтесь, спасибо за то, что вы дали такой проницательный ответ! – lmcphers