Преобразование изменяемой карты Seq в неизменяемую карту IndexedSeq в Scala - PullRequest
1 голос
/ 13 марта 2012

Мне нужно обработать большое количество записей (несколько миллионов), представляющих людей.Я хотел бы создать раздел, основанный на годе рождения, а затем обработать каждую группу отдельно.Я пытаюсь создать функциональное решение (без / минимальных изменяемых данных), чтобы оно было поточно-ориентированным и могло быть распараллелено.

Для моей первой попытки я создал хвостовую рекурсивную функцию, которая создаетMap[Int, IndexedSeq], который отображает каждый год рождения в последовательности записей о людях.Мне нужна индексированная последовательность, потому что я буду делать произвольный доступ к людям в каждой группе.Вот мой код:

@tailrec
def loop(people: Seq[Person],
         map: Map[Int, IndexedSeq[Person]] = Map()): Map[Int, IndexedSeq[Person]] = {
  if (people.isEmpty) map
  else {
    val person = people.head
    val yearOfBirth = person.yearOfBirth
    val seq = map.getOrElse(yearOfBirth, IndexedSeq())
    loop(people.tail, map + (yearOfBirth -> (seq :+ person)))
  }
}

Это работает, но не очень эффективно.Я могу добиться большего, разрешая небольшое количество очень локализованной изменчивости.Если все изменяемые переменные находятся в стеке, код по-прежнему будет потокобезопасным, пока вывод Map является неизменным.

Я хотел бы реализовать это путем внутреннего построения изменяемого Map[Int, List[Person]] а затем эффективно преобразовать его в неизменяемое Map[Int, IndexedSeq[Person]] в качестве возвращаемого значения.

Как можно преобразовать изменяемые элементы Map из List в неизменяемые Map[Int, IndexedSeq[Person]] наиболее эффективным способом?Обратите внимание, что нет особого порядка для людей в каждой группе года рождения.

1 Ответ

6 голосов
/ 13 марта 2012

Почему бы вам не использовать функцию groupBy черты Seq?(документация здесь: http://www.scala -lang.org / api / current / index.html # scala.collection.Seq )

def groupByYearOfBirth(people: Seq[Person]) = people.groupBy(_.yearofBirth)

Редактировать: вопреки моему первоначальному предложению, не используйте .mapValues(_.toIndexedSeq) to provide an IndexedSeq`.Даниил объясняет почему в комментарии ниже.

...