How to stay true to Scala's functional style for expressions

I struggled to find a way to stay true to the functional style for expressions, when I needed to collect several object parameters into a list.

As an example, let's say that I have a Notification object that has both fromId (the identifier of the user from which the notification comes) and objectOwnerId (identifier of the user who created the original object). They may differ in facebook style notifications ("X also commented on post Y").

I can compile userIds with such expression for expression

val userIds = for { notification <- notifications } yield notification.fromId

however, I will say that I want to collect both fromIds and objectOwnerIds into one list, is there a way to do this in one for an expression without the vars user?

In the past, I have done something like this:

var ids = List()
for {
    notification <- notifications
    ids = ids ++ List(notification.fromId, notification.objectOwnerId)
}
ids = ids.distinct

, . var . , , - .

!

+5
7

foldLeft:

(notifications foldLeft Set.empty[Id]) { (set, notification) =>
  set ++ Seq(notification.fromId, notification.ownerId)
}

:

(Set.empty[Id] /: notifications) { (set, notification) =>
  set ++ Seq(notification.fromId, notification.ownerId)
}

. , .

+9
val userIds = for { 
  notification <- notifications 
  id <- List(notification.fromId, notification.objectOwnerId)
} yield id

distinct , . , distinct .

+5

, , fromId,

val idPairs:List[(String, String)] = for(notification <- notifications) yield(notification.fromId, notification.objectOwnerId)
+4

, :

[Y (x1, x2), Y (x3, x4)] [x1, x2, x3, x4]?

flatMap (. Collection.Traversable, , ).

case class Y(a: Int, b: Int)
var in = List(Y(1,2), Y(3,4))
var out = in.flatMap(x => List(x.a, x.b))

> defined class Y
> in: List[Y] = List(Y(1,2), Y(3,4))
> out: List[Int] = List(1, 2, 3, 4)

, for..yield filter, map flatMap ( . "sugar for flatMap?" , , , : map):

var out = for { i <- in; x <- Seq(i.a, i.b) } yield x

, , .

.

+1

Stream :

def toStream(xs: Iterable[Y]): Stream[Int] = {
  xs match {
    case Y(a, b) :: t => a #:: b #:: toStream(t)
    case _ => Stream.empty
  }
}

, pst, , , :

val result = toStream(ys).toList.removeDuplicates

flatten - , Y :

def yToList(y: Y) = List(y.a, y.b)

:

val ys = List(Y(1, 2), Y(3, 4))
(ys map yToList flatten).removeDuplicates
+1

Dave, , , id User, . , , db .

0

map? AFAIK for yield flatMap map. :

notifications.map(n => (n.fromId, n.objectOwnerId)).distinct
-1

All Articles