scala: union of two maps whose key type is the same and whose value type is a collection of elements, but whose types are different

后端 未结 3 1098
半阙折子戏
半阙折子戏 2020-12-20 06:35

I would like to create a union of two maps whose key type is the same and whose value type is a collection of elements, but whose types are different.

Consider the f

3条回答
  •  感情败类
    2020-12-20 07:26

    Just for the curious, here's how it could be done using Scalaz:

    import scalaz._, Scalaz._
    
    case class Child(name: String)
    
    val peopleToChildren = Map(
      "max"     -> List(Child("a"), Child("b")), 
      "yaneeve" -> List(Child("y"), Child("d"))
    )
    
    case class Pet(name: String)
    
    val peopleToPets = Map(
      "max"  -> List(Pet("fifi")), 
      "jill" -> List(Pet("bobo"), Pet("jack"), Pet("Roger rabbit"))
    )
    
    val peopleToChildrenAndPets: Map[String, (List[Child], List[Pet])] = 
      peopleToChildren.strengthR(nil[Pet]) |+| peopleToPets.strengthL(nil[Child])
    

    Explanation:

    • nil[Pet] is just an alias for List.empty[Pet]
    • strengthR for a given Functor tuples contained values, so that its parameter is at the right. Here it is equivalent to peopleToChildren.mapValues(v => (v, nil[Pet]))
    • strengthL is the same, but element will be added to the left
    • |+| is an append operator for a given Semigroup. The one here is derived recursively:
      • for Map[K, V], it uses |+| to combine values of type V if a given key exists in both Maps. If the value is only present in one of them, it will be retained as is. Here, V = (List[Child], List[Pet])
      • for tuples (A, B), it again uses |+| to combine both As and Bs. Here, A = List[Child] and B = List[Pet]
      • for lists of any type (as well as strings, vectors or streams) it does concatenation. This is why I had to change type of Map values to be Lists - for generic Seqs this operation is not defined

    Result:

    peopleToChildrenAndPets: Map[String, (List[Child], List[Pet])] = Map(
      "max" -> (List(Child("a"), Child("b")), List(Pet("fifi"))),
      "jill" -> (
        List(),
        List(Pet("bobo"), Pet("jack"), Pet("Roger rabbit"))
      ),
      "yaneeve" -> (List(Child("y"), Child("d")), List())
    )
    

提交回复
热议问题