Reputation:
I'm working on an item-based collaborative filter, for which you need similarities between items. I have found that create a matrix like below works well, but I now want to prevent it from calculating doubles.
I'll explain what I mean with an example. Assume you have a list of 5 items, each with ratings to base the similarity on.
After calculating similarities, I have come up with the following matrix:
I1 | I2 | I3 | I4 | I5 |
I1 | 1 | 0.5| 0.3| 0.2| 0.9|
I2 | 0.5| 1 | 0.2| 0.1| 0.8|
I3 | 0.3| 0.2| 1 | 0.5| 0.1|
I4 | 0.2| 0.1| 0.5| 1 | 0.7|
I5 | 0.9| 0.8| 0.1| 0.7| 1 |
I'm doing this with the following code:
//allItems is a list of the 5 items
foreach (var item1 in allItems)
foreach (var item2 in allItems)
ComputeSimilarity(item1, item2);
//ComputeSimilarity(); returns a double, a.k.a. the similarity between items
You can ignore the inner workings of the function since it works fine, I just can't figure out to alter the code so it doesn't compute everything twice.
How can I alter this function to make the computed matrix look like this?
I1 | I2 | I3 | I4 | I5 |
I1 | | 0.5| 0.3| 0.2| 0.9|
I2 | | | 0.2| 0.1| 0.8|
I3 | | | | 0.5| 0.1|
I4 | | | | | 0.7|
I5 | | | | | |
Let me know if I should elaborate more! Thanks in advance!
Upvotes: 2
Views: 52
Reputation: 29421
try this
double val;
for (int i = 0; i < allItems.Count; i++)
{
for (int j = i; j < allItems.Count; j++)
{
if (i!=j)
val = ComputeSimilarity(allItems[i], allItems[j]);
}
}
Upvotes: 0
Reputation: 109567
This should do it:
int n = allItems.Length;
double[,] similarity = new double[n,n];
for (int i = 0; i < n; ++i)
{
for (int j = i + 1; j < n; ++j)
{
similarity[i, j] = computeSimilarity(allItems[i], allItems[j]);
}
}
Upvotes: 2
Reputation: 45947
You could add a check before calculation
for (int i = 0; i < allItems.Count;i++ )
for (int j = 0; j < allItems.Count; j++)
if(i<j)
ComputeSimilarity(allItems[i], allItems[j]);
Upvotes: 1