【问题标题】:How to group of Lists of Lists of Objects based on the first element of the list如何根据列表的第一个元素对对象列表的列表进行分组
【发布时间】:2018-12-24 22:07:48
【问题描述】:

如何根据列表的第一个元素对ObjectsLists 的列表进行分组?

我正在使用的一个库返回一个对象列表。

val result = (List(PersonObj(name=John,Id=23), LikesOrder(type=toys, order=1), ItemLiked(type=figurerine,id=23)), 
List( PersonObj(name=John,Id=23), LikesOrder(type=toys, order=2), ItemLiked(type=figurerine,id=32))
),List( PersonObj(name=Tiffanny,Id=32), LikesOrder(type=toys, order=1), ItemLiked(type=figurerine,id=23) ))

列表中的每个项目代表 1 次用户交互。在我提供的列表中,我们有 3 个交互条目。其中 2 个条目来自 John,其 id 为 23,并且有 2 个项目被喜欢。

我有办法做到这一点吗?

上面的结果会变成Map<PersonObj, List<ItemLiked>>的映射?

Scala 可以做到这一点吗?

【问题讨论】:

  • groupBy 有什么问题?

标签: scala


【解决方案1】:

你可以使用 groupBy 和 asInstanceOf,虽然这有点不安全(它可能会抛出):

@ result.groupBy(_(0).asInstanceOf[PersonObj])
res11: Map[PersonObj, List[List[Product with Serializable with Object]]] = Map(
  PersonObj("Tiffanny", 32) -> List(List(PersonObj("Tiffanny", 32), LikesOrder("toys", 1), ItemLiked("figurerine", 23))),
  PersonObj("John", 23) -> List(
    List(PersonObj("John", 23), LikesOrder("toys", 1), ItemLiked("figurerine", 23)),
    List(PersonObj("John", 23), LikesOrder("toys", 2), ItemLiked("figurerine", 32))
  )
)

然后您可以展平这些值,以便为每个 PersonObj 留下总和列表:

@ result.groupBy(_(0).asInstanceOf[PersonObj]).mapValues(_.flatten)
res12: Map[PersonObj, List[Product with Serializable with Object]] = Map(
  PersonObj("Tiffanny", 32) -> List(PersonObj("Tiffanny", 32), LikesOrder("toys", 1), ItemLiked("figurerine", 23)),
  PersonObj("John", 23) -> List(
    PersonObj("John", 23),
    LikesOrder("toys", 1),
    ItemLiked("figurerine", 23),
    PersonObj("John", 23),
    LikesOrder("toys", 2),
    ItemLiked("figurerine", 32)
  )
)

最后你可以只过滤掉ItemLiked:

@ result.groupBy(_(0).asInstanceOf[PersonObj]).mapValues(_.flatten.filter(_.isInstanceOf[ItemLiked]))
res13: Map[PersonObj, List[Product with Serializable with Object]] = Map(
  PersonObj("Tiffanny", 32) -> List(ItemLiked("figurerine", 23)),
  PersonObj("John", 23) -> List(ItemLiked("figurerine", 23), ItemLiked("figurerine", 32))
)

【讨论】:

    【解决方案2】:

    如果内部列表总是PersonObj,LikesOrder,ItemLiked 你可以

    case class PersonObj(name: String, Id: Int)
    case class LikesOrder(ttype: String, order: Int)
    case class ItemLiked(ttype: String, id: Int)
    
    
    
    val result = List(
      List(PersonObj(name="John",Id=23),
        LikesOrder(ttype="toys", order=1),
        ItemLiked(ttype="figurerine",id=23)),
      List( PersonObj(name="John",Id=23),
        LikesOrder(ttype="toys", order=2),
        ItemLiked(ttype="figurerine",id=32)),
      List( PersonObj(name="Tiffanny",Id=32),
        LikesOrder(ttype="toys", order=1),
        ItemLiked(ttype="figurerine",id=23) ))
    
    val r1 =result.map(l => {
      val List(p:PersonObj,_: LikesOrder,il : ItemLiked) = l
      (p -> il)
    })
    
    r1.groupBy{case (p,_)=>p}.map{case (p,l) => (p,l.map(_._2))}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多