8

我有两个清单:List(1,1,1) , List(1,0,1)

我想得到以下内容:

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

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

我只是在寻找上面第 1 点的答案。我可以使用迭代的方法来计算项目,但有没有更实用的方法?这是整个代码:

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))
  }
}
4

6 回答 6

13

对于第一个:

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
于 2013-07-23T14:10:34.613 回答
8

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

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
 * )

然后你需要做的就是在地图上查找

于 2013-07-23T15:32:04.320 回答
2

几乎与 Jatin 提出的解决方案相同,但您可以使用List.count更好的 lisibility:

def getSimilarity(l1: List[Int], l2: List[Int]) =
  l1.zip(l2).count({case (x,y) => x != y})
于 2013-07-23T14:16:22.533 回答
2
a.zip(b).filter(x => x._1 != x._2).size
于 2013-07-23T14:17:43.153 回答
1

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

a.zip(b).foldLeft(0)( (x,y) => if (y._1 + y._2 == 1) x + 1 else x )
于 2013-07-23T14:22:55.550 回答
0

1)你可以zip2个列表来获取列表(Int, Int),只收集对(1, 0)(0, 1)(1, 0)1(0, 1)替换-1并得到总和。如果 count of(1, 0)和 count of(0, 1)相同,则sum相等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)您可以使用filterandlength获取具有某些条件的元素的计数:

(l1 zip l2).filter{ _ == (1, 1) }.length
(l1 zip l2).collect{ case (1, 1) => () }.length
于 2013-07-23T14:17:00.657 回答