user4189129
user4189129

Reputation:

Filling up a matrix without doubles

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

Answers (3)

user3598756
user3598756

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

Matthew Watson
Matthew Watson

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

fubo
fubo

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

Related Questions