Ускорение метода, который перебирает текст и создает Map [Tuple2 [String, String], Int] Scala - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть метод в программе scala, который создает Map [Tuple2 [String, String], Int], но он работает очень медленно и не может обрабатывать много текста. Я не могу понять, как ускорить его и сделать его более эффективным. Любые предложения будут с благодарностью.

def createTuple(words: List[String]): Map[Tuple2[String, String], Int] = {
    var pairCountsImmutable = Map[Tuple2[String, String], Int]()
    val pairCounts = collection.mutable.Map(pairCountsImmutable.toSeq: _*)
    var i = 0
    for (i <- 0 to words.length - 2) {
        val currentCount: Int = pairCounts.getOrElse((words(i), words(i + 1)), 0)
        if (pairCounts.exists(_ == (words(i), words(i + 1)) -> currentCount)) {
            var key = pairCounts(words(i), words(i + 1))
            key = key + 1
            pairCounts((words(i), words(i + 1))) = key
        } else {
            pairCounts += (words(i), words(i + 1)) -> 1
        }
    }
    var pairCountsImmutable2 = collection.immutable.Map(pairCounts.toList: _*)
    return pairCountsImmutable2
}

Ответы [ 3 ]

0 голосов
/ 08 сентября 2018

Обновление

Я беззастенчиво позаимствовал ответ от TRuhland, чтобы дать эту улучшенную версию моего ответа, которая не ошибается с пустыми или одноэлементными списками:

def createTuple(words: List[String]): Map[Tuple2[String, String], Int] =
  words
    .zip(words.drop(1))
    .groupBy(identity)
    .mapValues(_.length)

Оригинал

Вы, кажется, считаете соседние пары слов списком слов. Если так, что-то вроде этого должно работать:

def createTuple(words: List[String]): Map[Tuple2[String, String], Int] =
  words
    .sliding(2)
    .map(l => (l(0), l(1)))
    .toList
    .groupBy(identity)
    .mapValues(_.length)

Это работает следующим образом

  1. sliding(2) создает список соседних пар слов
  2. map превращает каждую пару из List в кортеж
  3. groupBy группирует кортежи с одинаковым значением
  4. mapValues подсчитывает количество пар с одинаковым значением для каждой пары

Это может быть не совсем то, что вы хотите, но, надеюсь, это дает представление о том, как это можно сделать.

Как правило, не перебирайте список с помощью индекса, а пытайтесь преобразовать список в нечто, где вы можете перебирать значения.

Старайтесь не создавать Map элемент за элементом. Используйте groupBy или toMap.

0 голосов
/ 09 сентября 2018

Если мы сначала сведем ваш код к сути:

def createTuple(words: List[String]): Map[(String, String), Int] = {
    val pairCounts = collection.mutable.Map[(String, String), Int]()
    for (i <- 0 until words.length - 1) {
      val pair = (words(i), words(i + 1))
      pairCounts += (pair  -> (pairCounts.getOrElse(pair, 0) + 1))
    }
    pairCounts.toMap
  }

Чтобы повысить скорость, не используйте индексирование в списке (как уже упоминалось):

def createTuple(words: List[String]): Map[(String, String), Int] = {
  val map = collection.mutable.Map[(String, String), Int]()
  words
    .zip(words.tail)
    .foreach{ pair => 
       map += (pair -> (map.getOrElse((pair, 0) + 1)) }
  map.toMap
}
0 голосов
/ 08 сентября 2018

Ваша большая проблема в том, что words - это List, и все же вы индексируете его с помощью words(i).Это медленно.Измените его на Vector или переделайте свой алгоритм, чтобы не использовать индексацию.

Также, pairCounts.exists медленный, вы должны использовать contains, когда это возможно, так как это постоянное время на карте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...