在Scala中加入多个列表

时间:2018-08-08 06:59:01

标签: scala

我有一系列列表(假设以下3个列表),其中第一个元素都代表一个主键。

function checkusername(){
}
add_action( 'wp_ajax_checkusername', 'checkusername' );
add_action( 'wp_ajax_nopriv_checkusername', 'checkusername' );

我想将它们完全结合在一起,形成如下所示的新列表。您可以假设结果元组中的项目数预定为4

var A= List((1,"A"), (2,"B"), (3,"C"))
var B= List((1,"AA"), (2,"BB"), (3,"CC"), (4,"DD"))
var C= List((1,"AAA"), (3,"CCC"))

如何通过功能性方式和使用Scala实现这一目标?

4 个答案:

答案 0 :(得分:1)

让我们说您正在获得输入列表,例如

var A= List((1,"A"), (2,"B"), (3,"C"))
var B= List((1,"AA"), (2,"BB"), (3,"CC"), (4,"DD"))
var C= List((1,"AAA"), (3,"CCC"))

然后通过应用以下功能

List(A,B,C).flatten.groupBy(_._1).map{
  case (k,v) => k :: v.map(_._2)
}

您将获得输出

res0: scala.collection.immutable.Iterable[List[Any]] = List(List(2, B, BB), List(4, DD), List(1, A, AA, AAA), List(3, C, CC, CCC))

但是,如果您仍然想在输出中获取空字符串,则可以尝试以下

var A= List((1,"A"), (2,"B"), (3,"C"))
var B= List((1,"AA"), (2,"BB"), (3,"CC"), (4,"DD"))
var C= List((1,"AAA"), (3,"CCC"))

val intermediate = List(A,B,C).flatten.groupBy(_._1).map{
  case (k,v) => k :: v.map(_._2)
}

val maxSize = intermediate.map(_.size).max
intermediate.map{
  x =>  x.size== maxSize match {
    case true =>
      x
    case false =>
      x ::: List.fill(maxSize-x.size)("")
  }
}

这将为您获取输出

res0: scala.collection.immutable.Iterable[List[Any]] = List(List(2, "B", "BB", ), List(4, "DD", , ), List(1, "A", "AA", "AAA"), List(3, "C", "CC", "CCC"))

Tuples有性能限制,并且大小限制为22,因此强烈建议您使用列表。

答案 1 :(得分:1)

您可以使用尾部递归来解决

var a= List((1,"A"), (2,"B"), (3,"C"))
var b= List((1,"AA"), (2,"BB"), (3,"CC"), (4,"DD"))
var c= List((1,"AAA"), (3,"CCC"))

val lst: List[List[(Int, String)]] = List(a, b, c)

def fun(input: List[List[(Int, String)]]): List[Any] = {
@tailrec
def itr(acc: List[Any], inp: List[List[(Int, String)]], key: Int, maxKey: Int): List[Any] = {
  key match {
    case x if x > maxKey => acc
    case _ =>
      itr(acc ::: List(key :: inp.map(itemLst => {
      itemLst.find(_._1 == key).map(_._2).getOrElse("")
      })), inp, key + 1, maxKey)
  }
}
itr(List(), input, input.head.head._1, input.map(_.length).max)
}

println(fun(lst))

输出为

List(List(1, A, AA, AAA), List(2, B, BB, ), List(3, C, CC, CCC), List(4, , DD, ))

答案 2 :(得分:0)

正如评论中提到的那样,Scala中的元组受到限制,抽象化其笨拙可能会很麻烦。如果您希望这样做,可以看看Shapeless。

对于更直接(尽管不是很干净)的解决方案,将执行以下操作(使用针对两个不同 target 工具的实现):

val a = List((1,"A"), (2,"B"), (3,"C"))
val b = List((1,"AA"), (2,"BB"), (3,"CC"), (4,"DD"))
val c = List((1,"AAA"), (3,"CCC"))

def join4[K, V](empty: V)(pss: List[(K, V)]*): List[(K, V, V, V)] =
  pss.reduceOption(_ ++ _).fold(List.empty[(K, V, V, V)])(_.groupBy(_._1).mapValues(_.map(_._2)).collect {
    case (key, Nil) => (key, empty, empty, empty)
    case (key, List(a)) => (key, a, empty, empty)
    case (key, List(a, b)) => (key, a, b, empty)
    case (key, List(a, b, c)) => (key, a, b, c)
    case (key, list) => throw new RuntimeException(s"Group for $key is too long (${list.size} > 3)")
  }.toList)

def join5[K, V](empty: V)(pss: List[(K, V)]*): List[(K, V, V, V, V)] =
  pss.reduceOption(_ ++ _).fold(List.empty[(K, V, V, V, V)])(_.groupBy(_._1).mapValues(_.map(_._2)).collect {
    case (key, Nil) => (key, empty, empty, empty, empty)
    case (key, List(a)) => (key, a, empty, empty, empty)
    case (key, List(a, b)) => (key, a, b, empty, empty)
    case (key, List(a, b, c)) => (key, a, b, c, empty)
    case (key, List(a, b, c, d)) => (key, a, b, c, d)
    case (key, list) => throw new RuntimeException(s"Group for $key is too long (${list.size} > 4)")
  }.toList)

join4("")(a, b, c)
join5("")(a, b, c)

您可以使用此代码on Scastie

答案 3 :(得分:0)

正如在问题中提到的“我们可以假设结果元组中的项目数为predetermined to be 4”,以下解决方案仅根据请求的工作返回元组: 给出的列表是:

var A= List((1,"A"), (2,"B"), (3,"C"))
var B= List((1,"AA"), (2,"BB"), (3,"CC"), (4,"DD"))
var C= List((1,"AAA"), (3,"CCC"))

在Scala REPL中:

scala> val list1 = List(A,B,C).flatten
list1: List[(Int, String)] = List((1,A), (2,B), (3,C), (1,AA), (2,BB), (3,CC), (4,DD), (1,AAA), (3,CCC))

scala> val list2 = List(A,B,C).flatten.map(x=>x._2.toArray).flatten.distinct
list2: List[Char] = List(A, B, C, D)

然后使用上面的two lists,可以如下获得所需的resultList

scala> val resultList = 
          list2.map(x=>list1.filter(y=>y._2.contains(x))).map{
            case List() =>
            case List((a,b)) => (a,b,"","")
            case List((a,b),(_,c))=>(a,b,c,"")
            case List((a,b),(_,c),(_,d)) =>(a,b,c,d)    
        }
resultList: List[Any] = List((1,A,AA,AAA), (2,B,BB,""), (3,C,CC,CCC), (4,DD,"",""))

但是,如果我们确实关心empty string ""each tuple的位置,那么代码会有点冗长,因为我们必须考虑case语句中所有组合的情况,并且条件{{1 }},如下所示:

pattern matching

但是,应该注意的是,在使用元组进行此类操作时,类型信息将丢失并且难以用结果元组列表处理。最好改用List等其他数据结构。但是,这是根据问题中提到的要求解决的。