scala рассчитать количество вхождений элемента - PullRequest
0 голосов
/ 09 мая 2018

У меня есть следующий список в качестве ввода:

val lisinputt=("banana  10",
          "apple   20",
          "apple   30",
          "banana   10",  
          "berry    10")

и я хочу вычислить количество вхождений для каждого элемента, а не суммы значений, связанных с каждым элементом, следовательно, требуемый результат будет:

val listoutput=("banana  2 20",
          "apple 2  50",  
          "berry  1  10")

Любая идея, как этого добиться, пожалуйста

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Вы можете рассчитывать на вывод, как это

val listInput=("banana  10",
  "apple   20",
  "apple   30",
  "banana   10",
  "berry    10")
val result = listInput.productIterator.toList.map(_.toString.split("\\s+")).groupBy(e=> e.apply(0)).collect{
  case e=> (e._1, e._2.size, e._2.map(_.apply(1).toInt).sum)
}
//result: scala.collection.immutable.Iterable[(String, Int, Int)] = List((banana,2,20), (apple,2,50), (berry,1,10))
0 голосов
/ 11 мая 2018

Оба ответа являются полностью правильными, учитывая ваши исходные данные. Однако мой ответ предполагает, что ваш вклад не ограничен предоставленной формой.

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

Для вашего примера это будет выглядеть так:

val = lisinputt = List(
    ("banana", 10),
    ("apple", 20),
    ("apple", 30),
    ("banana", 10),
    ("berry", 10))

Затем, используя приведенные ниже, вы можете получить доступ и объединить списки.

val aggreagatedList = lisinputt.groupBy(_._1).map {
    case (fruit, number) => ( fruit, number.size , number.map(_._2).sum )
}

По сути, это делает то же самое, что и оба других ответа (посмотрите на случай e =>, и вы увидите сходство), однако в обоих ответах есть логика для изменения вашего ввода, чтобы он мог быть агрегирован.

В этой команде происходит несколько вещей, которые стоит объяснить:

  1. Во-первых, groupBy, примененный к lisinputt, будет сортировать по уникальным параметрам
  2. _._ 1 означает первую запись всех кортежей (параметр для groupBy)
  3. case (fruit, member) присваивает переменные 1-му и 2-му элементам в вашем кортеже (вы можете указать это как одну переменную, но это сделает методы доступа менее читаемыми
  4. означает, что => для каждого уникального случая (описанного выше для groupBy) возвращает запись кортежа, первым элементом которого является имя, вторым - вхождения, а третьим - суммирование всех вторых записей совпадающих фруктов в оригинале. кортеж.

Надеюсь, это поможет, я тоже учусь, поэтому, если в решении есть ошибки или мое понимание этих функций, я только рад принять исправления.

0 голосов
/ 09 мая 2018

Вы можете сделать что-то вроде ниже

val lisinputt=("banana  10",
  "apple   20",
  "apple   30",
  "banana   10",
  "berry    10")

lisinputt.productIterator.toList
  .map(x => {val splitted = x.toString.split("\\s+"); (splitted(0), 1, splitted(1))})
  .groupBy(_._1)
  .mapValues(x => (x.map(_._2.toInt).sum, x.map(_._3.toInt).sum))
  .map(x => Array(x._1, x._2._1, x._2._2).mkString(" "))
  .foreach(println)

что должно дать вам

banana 2 20
apple 2 50
berry 1 10
...