Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a comparison function in C#

Say I have elements (X, Y, and Z) in a list, I have a function, that generates a percentage, of how much two objects resemble each other.

What I want to do, is run X against Y and Z using my compareElements, so:

compareElements(X,Y); // equals 55
compareElements(X,Z); // equals 60

Then Y against X and Z

compareElements(Y,X); // equals 55
compareElements(Y,Z); // equals 62

Then Z against Y and X

compareElements(Z,X); // equals 60
compareElements(Z,Y); // equals 62

Then, I return the highest value, which is 62.

Obviously, there's some repetition there, I don't need the repetition, but I'm not sure how to eliminate it.

How do I structure my LINQ query, or a function/algorithm to do this comparison on every element, without the repetition?

I'd prefer to use LINQ if I can, as I'm being passed an enumerable and the function returns before the list is actually enumerated, so we can save the cost of performing the compare, until the list is enumerated.

All I need is that highest value, of the compare functions, 62.

Note: My actual result set I'm working with averages between 3 and 10 elements in the list, that need to be ran through this compare function.

like image 222
Brian Deragon Avatar asked Dec 19 '11 20:12

Brian Deragon


2 Answers

I'd be inclined to do it like this:

int count = list.Count;
var query = from index1 in Enumerable.Range(0, count)
            from index2 in Enumerable.Range(index1 + 1, count - (index1 + 1))
            select ComputeSimilarity(list[index1], list[index2]);
var maxSimilarity = query.Max();
like image 149
Eric Lippert Avatar answered Sep 24 '22 13:09

Eric Lippert


I'm not sure I'm understanding you correctly, but try something like this:

    public int compareElementList(List<Element> elements)
    {
        int result = 0;
        for (int i = 0; i < elements.Count - 1; i++)
        {
            for (int q = i + 1; q < elements.Count; q++)
            {
                result = Math.Max(result, compareElements(elements[i], elements[q]));
            }
        }

        return result;
    }

This will eliminate the duplicate comparisons for you. It doesn't use LINQ, but I think it's still pretty readable.

UPDATE: Here is my version modified to handle IEnumerables. It varies from Jon Hanna's in that it doesn't create a new List, it just keeps track of two iterators.

    public int compareElementEnumerable(IEnumerable<Element> elements)
    {
        int result = 0, i = 0, q = 1;
        foreach (Element el in elements)
        {
            foreach (Element el2 in elements)
            {
                if (q > i)
                {
                    result = Math.Max(result, compareElements(el, el2));
                }
                q++;
            }
            i++;
        }

        return result;
    }
like image 37
smelch Avatar answered Sep 26 '22 13:09

smelch