2

我仍然不精通 scala,但我正在使用它来处理一些数据,这些数据是我从文件中读取到以下数据结构中的:

Map[Id, (Set[Category], Set[Tag])]

在哪里

type Id = String

type Category = String

type Tag = String

本质上, 中的每个键Map都是与一组类别和一组标签相关联的实体的唯一 ID。

我的问题是:这是最好的(=最有效和最惯用的)计算方法:

  • 标记所有实体的频率 ( type TagsFrequencies = Map[Tag, Double])
  • 每个类别的标签频率 ( Map[Category, TagsFrequencies])

这是我的尝试:

def tagsFrequencies(tags: List[Tag]): TagsFrequencies =
  tags.groupBy(t => t).map(
    kv => (kv._1 -> kv._2.size.toDouble / tags.size.toDouble))

def computeTagsFrequencies(data: Map[Id, (Set[Category], Set[Tag])]): TagsFrequencies = {
  val tags = data.foldLeft(List[Tag]())(
    (acc, kv) => acc ++ kv._2._2.toList)
  tagsFrequencies(tags)
}

def computeTagsFrequenciesPerCategory(data: Map[Id, (Set[Category], Set[Tag])]): Map[Category, TagsFrequencies] = {

  def groupTagsPerCategory(data: Map[Id, (Set[Category], Set[Tag])]): Map[Category, List[Tag]] =
    data.foldLeft(Map[Category, List[Tag]]())(
      (acc, kv) => kv._2._1.foldLeft(acc)(
        (a, category) => a.updated(category, kv._2._2.toList ++ a.getOrElse(category, Set.empty).toList)))

  val tagsPerCategory = groupTagsPerCategory(data)
  tagsPerCategory.map(tpc => (tpc._1 -> tagsFrequencies(tpc._2)))
}

例如,考虑

val data = Map(
  "id1" -> (Set("c1", "c2"), Set("t1", "t2", "t3")),
  "id2" -> (Set("c1"), Set("t1", "t4")))

然后:

所有实体的标签频率为:

Map(t3 -> 0.2, t4 -> 0.2, t1 -> 0.4, t2 -> 0.2)

每个类别的标签频率是:

Map(c1 -> Map(t3 -> 0.2, t4 -> 0.2, t1 -> 0.4, t2 -> 0.2), c2 -> Map(t3 -> 0.3333333333333333, t1 -> 0.3333333333333333, t2 -> 0.3333333333333333))
4

1 回答 1

2

这是对成语的重写,不一定是效率。我会让你的第一个方法更通用(Iterable参数),使用identity而不是t => t,并使用mapValues

def tagsFrequencies(tags: Iterable[Tag]): TagsFrequencies =
  tags.groupBy(identity).mapValues(_.size / tags.size.toDouble)

因为这现在需要 any Iterable[Tag],所以您可以使用它来清理第二种方法:

def computeTagsFrequencies(data: Map[Id, (Set[Category], Set[Tag])]) =
  tagsFrequencies(data.flatMap(_._2._2))

同样对于最后一种方法:

def computeTagsFrequenciesPerCategory(data: Map[Id, (Set[Category], Set[Tag])]) =
  data.values.flatMap {
    case (cs, ts) => cs.map(_ -> ts)
  }.groupBy(_._1).mapValues(v => tagsFrequencies(v.flatMap(_._2)))

这些更改都不应该以任何有意义的方式影响性能,但是您当然应该在自己的应用程序中进行基准测试。

于 2012-11-26T18:28:52.693 回答