分组:用于 scala 与 .net linq 中的理解

发布于 2024-11-01 16:42:42 字数 617 浏览 0 评论 0原文

在阅读有关 scala 中的for compressives 的内容时,我有一种由 .net 的 linq 引起的似曾相识的效果。
它们都允许简洁的序列定义。

现在 - 问题是如何使用 进行理解来简洁地表示分组?

更具体地说。这在 C# 中:

from entry in new[] {
    new { Name="Joe", ShoeSize="23" },
    new { Name="Alice", ShoeSize="23" },
    new { Name="Mary", ShoeSize="17" },
    new { Name="Yeti", ShoeSize="170" },
}
group entry by entry.ShoeSize into grouped
select grouped;

产生:

Key=23, Items=(Joe, Alice)
Key=17, Items=(Mary)
Key=170, Items=(Yeti)

如何使用 scala for 理解 简洁地实现相同的效果?

Reading about for comprehensions in scala I had a deja vu effect caused by .net's linq.
They both allow for a concise sequence definition.

Now - the question is how to concisely represent grouping using a for comprehension?

To be more specific. This in C#:

from entry in new[] {
    new { Name="Joe", ShoeSize="23" },
    new { Name="Alice", ShoeSize="23" },
    new { Name="Mary", ShoeSize="17" },
    new { Name="Yeti", ShoeSize="170" },
}
group entry by entry.ShoeSize into grouped
select grouped;

Produces:

Key=23, Items=(Joe, Alice)
Key=17, Items=(Mary)
Key=170, Items=(Yeti)

How to achieve the same concisely with scala for comprehensions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

み青杉依旧 2024-11-08 16:42:43

不需要理解

val entry = List(new { val name="Joe";   val shoeSize="23" },
                 new { val name="Alice"; val shoeSize="23" },
                 new { val name="Mary";  val shoeSize="17" },
                 new { val name="Yeti";  val shoeSize="170" })

val grouped = entry.groupBy(_.shoeSize)

There is no need of for comprehensions:

val entry = List(new { val name="Joe";   val shoeSize="23" },
                 new { val name="Alice"; val shoeSize="23" },
                 new { val name="Mary";  val shoeSize="17" },
                 new { val name="Yeti";  val shoeSize="170" })

val grouped = entry.groupBy(_.shoeSize)
怀中猫帐中妖 2024-11-08 16:42:43
List("Joe"->"23",
     "Alice"->"23",
     "Mary"->"17",
     "Yeti"->"170").groupBy(_._2).mapValues(_.map(_._1))

//--> Map(23 -> List(Joe, Alice), 170 -> List(Yeti), 17 -> List(Mary))

请注意,如果您需要命名参数(姓名和鞋号),则可以使用案例类。丑陋的 mapValues 部分只需要从元组中提取名称部分,否则你会得到 Map(23 -> List((Joe,23), (Alice,23)), 170 -> List((Yeti,170)), 17 -> List((Mary,17))),这通常“足够好”。

List("Joe"->"23",
     "Alice"->"23",
     "Mary"->"17",
     "Yeti"->"170").groupBy(_._2).mapValues(_.map(_._1))

//--> Map(23 -> List(Joe, Alice), 170 -> List(Yeti), 17 -> List(Mary))

Note that you can use case classes if you want named arguments (name and shoe size). The ugly mapValues part is only necessary to extract the name part from the tuple, elso you get Map(23 -> List((Joe,23), (Alice,23)), 170 -> List((Yeti,170)), 17 -> List((Mary,17))), which is often "good enough".

对风讲故事 2024-11-08 16:42:43

您可以使用 List#groupBy() 按特定字段对其进行分组。

case class Person(name: String, shoeSize: Int)

val persons = List(
    Person("Joe", 23),
    Person("Alice", 23),
    Person("Mary", 17),
    Person("Yeti", 170)
)

val groupByShoeSize = persons.groupBy(_.shoeSize)

// Now groupByShoeSize is a Map[Int, List[Person]]

println(groupByShoeSize)

// Map((17,List(Person(Mary,17))), (23,List(Person(Joe,23), Person(Alice,23))), (170,List(Person(Yeti,170))))

You could use List#groupBy() to group it by a certain field.

case class Person(name: String, shoeSize: Int)

val persons = List(
    Person("Joe", 23),
    Person("Alice", 23),
    Person("Mary", 17),
    Person("Yeti", 170)
)

val groupByShoeSize = persons.groupBy(_.shoeSize)

// Now groupByShoeSize is a Map[Int, List[Person]]

println(groupByShoeSize)

// Map((17,List(Person(Mary,17))), (23,List(Person(Joe,23), Person(Alice,23))), (170,List(Person(Yeti,170))))
红尘作伴 2024-11-08 16:42:42

Scala 的理解能力没有分组能力。它只是 mapflatMapfilter 的组合(实际上是 withFilter,但是 filter< /code> 更容易理解),或者 foreachfilter

它们背后的原理并不完全不同,但是 LINQ 是在 SQL 之后建模的,而 for commplion 是在单元转换之后建模的。例如,为了便于理解,您的示例可能会使用以下内容进行建模:

for {
    (shoeSize, groups) <- entry groupBy (_.shoeSize)
    names = for (group <- groups) yield group.name
    grouped = (shoeSize, names)
} 
yield grouped

我希望 LINQ 会做几乎相同的事情,但它包含这些转换作为其基本语法的一部分,因为这是预期的。

Scala's for comprehension have no grouping ability. It is just a combination of map, flatMap and filter (actually, withFilter, but filter is easier to understand), or foreach and filter.

The principle behind them is not completely different, but LINQ was modeled after SQL, while for comprehension is modeled after monadic transformations. For instance, your example might be modeled with the following for comprehension:

for {
    (shoeSize, groups) <- entry groupBy (_.shoeSize)
    names = for (group <- groups) yield group.name
    grouped = (shoeSize, names)
} 
yield grouped

I expect LINQ is doing pretty much the same thing, but it includes these transformations as part of its basic syntax because it is expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文