Question: I have two lists : `List(1,1,1) , List(1,0,1)`

I want to get the following : 

1. A count of every element that contains a 1 in first list and a 0 in the corresponding list at same position and vice versa.
In above example this would be 1 , 0 since the first list contains a 1 at middle position and second list contains a 0 at same position (middle).
2. A count of every element where 1 is in first list and 1 is also in second list.
In above example this is two since there are two 1's in each corresponding list. I can get this using the intersect method of class List.

I am just looking an answer to point 1 above. I could use an iterative a approach to count the items but is there a more functional method ?
Here is the entire code : 

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

```

Answer: 
You can count all combinations easily and have it in a map with

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

```

---

The trick is a common one

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

```

Then all you need to do is lookup on the map
1) You could `zip` 2 lists to get list of `(Int, Int)`, collect only pairs `(1, 0)` and `(0, 1)`, replace `(1, 0)` with `1` and `(0, 1)` with `-1` and get sum. If count of `(1, 0)` and count of `(0, 1)` are the same the `sum` would be equal `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

```

You could use `view` method to prevent creation intermediate collections.

2) You could use `filter` and `length` to get count of elements with some condition:

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

```