Как я могу обработать эти большие данные в Scala IntelliJ? - PullRequest
0 голосов
/ 02 февраля 2019

Прошло несколько дней, и я начал изучать Scala на IntelliJ, и я изучаю все сам.Пожалуйста, нести мои ошибки новичка.У меня есть CSV-файл с более чем 10000 строк и 13 столбцов.

Заголовок столбцов:

Категория |Рейтинг |Отзывы |Размер |Устанавливает |Тип |Цена |Рейтинг контента |ЖанрыПоследнее обновление |Текущая версия |Версия Android

Мне удалось прочитать и отобразить файл csv со следующим кодом:

import scala.io.Source


object task {
  def main(args: Array[String]): Unit = {
    for(line <- Source.fromFile("D:/data.csv"))
    {
      println(line)
    }
  }
}

Проблема в том, что этот код отображает один алфавитили цифра, перемещается на следующую строку и отображает следующий алфавит или цифру.Он не отображает строку в одну строку.

Я хочу найти лучшее приложение для каждой категории (ART_AND_DESIGN, AUTO_AND_VEHICLES, BEAUTY…,) на основе назначенных ему приоритетов обзоров и рейтингов.Приоритеты определены как 60% для «обзоров» и 40% для «рейтинговых» столбцов соответственно.Рассчитайте значение для каждой категории (ART_AND_DESIGN, AUTO_AND_VEHICLES, BEAUTY ...,), используя эти присвоенные значения приоритетов.Это значение поможет нам найти лучшее приложение в каждой категории.Вы можете использовать уравнение формулы Приоритета следующим образом.

Приоритет = ((((рейтинг / max_rating) * 100) * 0,4) + (((отзывы / max_reviews) * 100) * 0,6))

Здесь max_rating - это максимальный рейтинг данных в той же категории, например в категории («ART_AND_DESIGN»), максимальный рейтинг - «4,7», max_reviews - максимальный отзыв приложения в той же категории, например в категории («ART_AND_DESIGN»), максимальный отзыв - «295221».Таким образом, значение приоритета будет для первой записи данных категории («ART_AND_DESIGN»):

Рейтинг = 4,1, отзывы = 159,

max_rating = 4,7, max_reviews = 295221

Мой вопрос, как я могу хранить каждый столбец в массиве?Вот как я планирую вычислить данные.Если есть какой-либо другой способ решения вышеуказанной проблемы, я открыт для предложений.

Я могу загрузить небольшой кусок данных, если кто-то захочет.

1 Ответ

0 голосов
/ 02 февраля 2019

Source дает вам байт Iterator по умолчанию.Чтобы перебрать строки, используйте .getLines:

 Source.fromFile(fileName)
   .getLines
   .foreach(println)

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

  val arrays = Source.fromFile(fileName).getLines.map(_.split("|"))

Itлучше избегать использования сырых массивов.Создание класса case делает намного лучше читаемый код:

   case class AppData(
     category: String,
     rating: Int,
     reviews: Int, 
     size: Int,
     installs: Int, 
     `type`: String, 
     price: Double,
     contentRating: Int, 
     generes: Seq[String], 
     lastUpdated: Long,
     version: String,
     androidVersion: String
  ) {
     def priority(maxRating: Int, maxReview: Int) = 
       if(maxRatings == 0 || maxReviews == 0) 0 else 
         (rating * 0.4 / maxRating + reviews * 0.6 /maxReview) * 100
  }

  object AppData {
    def apply(str: String) = {
       val fields = str.split("|")
       assert(fields.length == 12)
       AppData(
         fields(0),
         fields(1).toInt,   
         fields(2).toInt,
         fields(3).toInt,
         fields(4).toInt,
         fields(5),
         fields(6).toDouble,
         fields(7).toInt,
         fields(8).split(",").toSeq,
         fields(9).toLong,
         fields(10),
         fields(11)
       )
    }
  }

Теперь вы можете делать все, что хотите, аккуратно:

  // Read the data, parse it and group by category
  // This gives you a map of categories to a seq of apps 
  val byCategory = Source.fromFile(fileName)
    .map(AppData)
    .groupBy(_.category)

  // Now, find out max ratings and reviews for each category
  // This could be done even nicer with another case class and 
  // a monoid, but tuple/fold will do too 
  // It is tempting to use `.mapValues` here, but that's not a good idea
  // because .mapValues is LAZY, it will recompute the max every time 
  // the value is accessed!
  val maxes = byVategory.map { case (cat, data) => 
     cat -> 
        data.foldLeft(0 -> 0) { case ((maxRatings, maxReviews), in) => 
          (maxRatings max in.rating, maxReviews max in.reviews)
        }
  }.withDefault( _ => (0,0))

  // And finally go through your categories, and find best for each, 
  // that's it!
  val bestByCategory = byCategory.map { case(cat, apps) => 
    cat -> apps.maxBy { _.priority.tupled(maxes(cat)) }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...