我仍然不精通 scala,但我正在使用它来处理一些数据,我将这些数据从文件读入以下数据结构:
map [Id,(集[类别],集[标签])]
哪里
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))
最佳答案
这里是对惯用语的重写,不一定是效率。我会让你的第一个方法更通用一些(Iterable
参数),使用identity
而不是t => t
,并使用mapValues
:
def tagsFrequencies(tags: Iterable[Tag]): TagsFrequencies =
tags.groupBy(identity).mapValues(_.size / tags.size.toDouble)
因为现在需要任何 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)))
这些更改都不会以任何有意义的方式影响性能,但您当然应该在自己的应用程序中进行基准测试。
关于scala - 在 scala 中映射转换(计算标签频率),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13570120/