0

I am trying to return a number that represents the similarity between two arrays.
I.e :

Array1: {Katy, Jenny, Sarah, Ben, Jill, Tina} 
Array2: {Katy, John, Sam, Ben, Jill, Linda}

I want to return the number 3 because three comparisons are correct. Is this possible? I can't think of any functions that will do this for me.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880

6 Answers6

5

This is how you can count the amount of items that are equal in matching indices.

var c = arr1.Where((x, i) => x.Equals(arr2[i])).Count();

Note that you might want to assure that you don't try to access arr2 in an index that is out of range:

var c = arr1.Take(arr2.Length).Count(...);

If you don't care about index positions, you should use nemesv's solution.

SimpleVar
  • 14,044
  • 4
  • 38
  • 60
  • Does you sample compiles? I don't know a [Count method](http://msdn.microsoft.com/en-us/library/bb357758.aspx) which takes a Func with two arguments... – nemesv Oct 11 '12 at 05:12
  • Based on the OPs comment " if it is in {3} position in array 1 it must be in {3} position in array 2" your solution with the `Where((x, i)...` is the correct one. – nemesv Oct 11 '12 at 05:15
  • @nemesv Looks like it. By the way, I think that you can come up with a better solution than intersect, by sorting them and having two indices that increment side-by-side-ish (assuming the question was the one you answered). – SimpleVar Oct 11 '12 at 05:17
1

There are many ways to do this. Since others have already specified a few ways, I will try to post a different way of doing the same.

If you consider matching based on index, you can do something like this using Zip

var cnt = 0;
Array1.Zip(Array2,(a,b)=>{
    if(a.Equals(b)) ++cnt; 
    return string.Empty; //we dont need this
}).Count(); // use tolist or count to force evaluation

If you don't care about ordering and are just concerned about matching, you can use Intersect

Array1.Intersect(Array2).Count()
prashanth
  • 2,059
  • 12
  • 13
  • This won't work. LINQ methods are lazy-evaluated, so if the collection is never enumerated, the counter will never be incremented. – Matthew Kennedy Oct 11 '12 at 07:05
0

The way I would approach this problem is too take the value in the first array and compare it with every other value in the second array. If they match than increase a compare counter and that will tell you their are three comparisons that match.

Mike
  • 1
  • 1
  • 1
    The name must be in the exact same position. I.e if it is in {3} position in array 1 it must be in {3} position in array 2. –  Oct 11 '12 at 05:10
0

This works for me:

var array1 = new string[] {"Katy", "Jenny", "Sarah", "Ben", "Jill", "Tina"};
var array2 = new string[] {"Katy", "John", "Sam", "Ben", "Jill", "Linda"};

var similarity = (array1.Length + array2.Length) - array1.Union(array2).Count();

Edit: Oh just saw you want them to be in the same position.

Zac Charles
  • 1,208
  • 14
  • 19
0

You're saying "According to index", assuming you mean that if "John" is on position 1 in the first list, and on position 2 on the second list => no match.

In that case:

int maxItems = Math.Min(arr1.Length, arr2.Length);
int matchCount = 0;

for(int i = 0; i < maxItems; i++)
{
  if(object.Equals(arr1[i], arr2[i]))
    matchCount++;
}
tofi9
  • 5,775
  • 4
  • 29
  • 50
0

I'd do it like this:

int count = array1.Zip(array2, (a, b) => a.Equals(b)).Count(b => b);

The zip part returns an IEnumerable<bool> and the count part count how many times true occurs in that list.

Matthew Kennedy
  • 616
  • 4
  • 19