Scala 比较两个列表中的项目

Scala 比较两个列表中的项目,scala,Scala,我有两个列表:List(1,1,1),List(1,0,1) 我想得到以下信息: 第一个列表中包含1且相应列表中相同位置包含0的每个元素的计数,反之亦然。 在上面的示例中,这将是1,0,因为第一个列表在中间位置包含1,而第二个列表在相同位置(中间)包含0 每个元素的计数,其中1在第一个列表中,1也在第二个列表中。 在上面的示例中,这是两个,因为每个对应列表中有两个1。我可以使用类列表的intersect方法得到这个 我只是想找到上面第1点的答案。我可以使用迭代a方法来计算项目,但是否有更实用的方

我有两个列表:
List(1,1,1),List(1,0,1)

我想得到以下信息:

  • 第一个列表中包含1且相应列表中相同位置包含0的每个元素的计数,反之亦然。 在上面的示例中,这将是1,0,因为第一个列表在中间位置包含1,而第二个列表在相同位置(中间)包含0

  • 每个元素的计数,其中1在第一个列表中,1也在第二个列表中。 在上面的示例中,这是两个,因为每个对应列表中有两个1。我可以使用类列表的intersect方法得到这个

  • 我只是想找到上面第1点的答案。我可以使用迭代a方法来计算项目,但是否有更实用的方法? 以下是完整的代码:

    class Similarity {
      def getSimilarity(number1: List[Int], number2: List[Int]) = {
        val num: List[Int] = number1.intersect(number2)
        println("P is " + num.length)
      }
    }
    
    object HelloWorld {
      def main(args: Array[String]) {
        val s = new Similarity
        s.getSimilarity(List(1, 1, 1), List(1, 0, 1))
      }
    }
    
    对于第一个:

    scala> val a = List(1,1,1)
    a: List[Int] = List(1, 1, 1)
    
    scala> val b = List(1,0,1)
    b: List[Int] = List(1, 0, 1)
    
    scala> a.zip(b).filter(x => x._1==1 && x._2==0).size
    res7: Int = 1
    
    第二项:

    scala> a.zip(b).filter(x => x._1==1 && x._2==1).size
    res7: Int = 2
    

    与Jatin提出的解决方案几乎相同,只是您可以使用
    List.count
    以获得更好的可理解性:

    def getSimilarity(l1: List[Int], l2: List[Int]) =
      l1.zip(l2).count({case (x,y) => x != y})
    
    1) 您可以使用
    zip
    2个列表来获取
    (Int,Int)
    列表,只收集
    (1,0)
    (0,1)
    ,将
    (1,0)
    替换为
    1
    ,将
    (0,1)
    替换为
    -1
    ,并获取总和。如果
    (1,0)
    的计数与
    (0,1)
    的计数相同,则
    总和将相等
    0

    val (l1, l2) = (List(1,1,1) , List(1,0,1))
    
    (l1 zip l2).collect{
      case (1, 0) => 1
      case (0, 1) => -1
    }.sum == 0
    
    您可以使用
    view
    方法阻止创建中间集合

    2) 您可以使用
    filter
    length
    获取具有某些条件的元素计数:

    (l1 zip l2).filter{ _ == (1, 1) }.length
    (l1 zip l2).collect{ case (1, 1) => () }.length
    

    您也可以使用foldLeft。假设没有非负数:

    a.zip(b).foldLeft(0)( (x,y) => if (y._1 + y._2 == 1) x + 1 else x )
    

    您可以轻松地计算所有组合,并将其放在具有

    def getSimilarity(number1 : List[Int] , number2 : List[Int]) = {
    
      //sorry for the 1-liner, explanation follows 
      val countMap = (number1 zip number2) groupBy (identity) mapValues {_.length}
    
    }
    
    /*
     * Example
     * number1 = List(1,1,0,1,0,0,1)
     * number2 = List(0,1,1,1,0,1,1)
     * 
     * countMap = Map((1,0) -> 1, (1,1) -> 3, (0,1) -> 2, (0,0) -> 1)
     */
    

    这个把戏很常见

    // zip the elements pairwise
    
    (number1 zip number2) 
    
    /* List((1,0), (1,1), (0,1), (1,1), (0,0), (0,1), (1,1))
     *
     * then group together with the identity function, so pairs
     * with the same elements are grouped together and the key is the pair itself
     */ 
    
    .groupBy(identity) 
    
    /* Map( (1,0) -> List((1,0)), 
     *      (1,1) -> List((1,1), (1,1), (1,1)), 
     *      (0,1) -> List((0,1), (0,1)), 
     *      (0,0) -> List((0,0))
     * )
     *
     * finally you count the pairs mapping the values to the length of each list
     */
    
    .mapValues(_.length)
    
    /* Map( (1,0) -> 1, 
     *      (1,1) -> 3, 
     *      (0,1) -> 2, 
     *      (0,0) -> 1
     * )
    

    那么你所需要做的就是在地图上查找

    难道你不能说
    x=>x.\u1==1&&x.\u2==0
    ?实际上你可以用
    count(谓词)
    替换
    filter(谓词)
    来代替
    count(谓词)
    为什么不干脆
    l1.zip(l2).count{case(x,y)=>x!=y}
    ,因为我第一次写它的时候没有想到要用
    count。我正在更新答案
    
    // zip the elements pairwise
    
    (number1 zip number2) 
    
    /* List((1,0), (1,1), (0,1), (1,1), (0,0), (0,1), (1,1))
     *
     * then group together with the identity function, so pairs
     * with the same elements are grouped together and the key is the pair itself
     */ 
    
    .groupBy(identity) 
    
    /* Map( (1,0) -> List((1,0)), 
     *      (1,1) -> List((1,1), (1,1), (1,1)), 
     *      (0,1) -> List((0,1), (0,1)), 
     *      (0,0) -> List((0,0))
     * )
     *
     * finally you count the pairs mapping the values to the length of each list
     */
    
    .mapValues(_.length)
    
    /* Map( (1,0) -> 1, 
     *      (1,1) -> 3, 
     *      (0,1) -> 2, 
     *      (0,0) -> 1
     * )