группировка: для понимания в scala vs .net linq - PullRequest
1 голос
/ 15 апреля 2011

Читая о for comprehensions в scala, у меня был эффект дежавю, вызванный linq.
.net. Оба они позволяют дать краткое определение последовательности.

Теперь - вопрос в том, как краткопредставлять группировку, используя for comprehension?

Чтобы быть более конкретным.Это в 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 comprehensions?

Ответы [ 4 ]

4 голосов
/ 15 апреля 2011

Скалы для понимания не имеют группирующей способности.Это просто комбинация map, flatMap и filter (на самом деле withFilter, но filter легче понять) или foreach и filter.

.Принцип, стоящий за ними, не совершенно другой, но LINQ был смоделирован после SQL, в то время как для понимания смоделирован после монадических преобразований.Например, ваш пример может быть смоделирован следующим образом:

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

Я ожидаю, что LINQ делает почти то же самое, но включает эти преобразования как часть своего основного синтаксиса, потому что это ожидается.

2 голосов
/ 15 апреля 2011

Нет необходимости 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)
1 голос
/ 15 апреля 2011
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))

Обратите внимание, что вы можете использовать case-классы, если вам нужны именованные аргументы (имя и размер обуви).Некрасивая часть mapValues необходима только для извлечения части имени из кортежа, также вы получаете Map(23 -> List((Joe,23), (Alice,23)), 170 -> List((Yeti,170)), 17 -> List((Mary,17))), что часто "достаточно хорошо".

1 голос
/ 15 апреля 2011

Вы можете использовать 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))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...