benjgorman
benjgorman

Reputation: 722

How to sort a collection of objects, which has to be sorted based on some constantly changing parameters

I'm looking on how to sort a list effectively using weighted values.

Each item has an id, name and filepath. Each item also has a list of values which are assigned a percentage, showing how relevant they are to each value.

I need the list to be sorted so that the items which are at the top end of the list are the ones which are the most relevant to the current parameters.

Lets say,

Item One:

Item Two:

And my parameters are A and Z. Clearly Item Two should be at the top of my list as it's the most relevant item. But how would I go about implementing this?

Bonus: Would be nice to be able to have a slight randomisation as well, I don't want to be served the definitive relevant item each time.

Thanks

Upvotes: 2

Views: 1634

Answers (2)

djskinner
djskinner

Reputation: 8125

A long time ago I created an extension method just for this purpose. I've just came across the need for it again:

public static IOrderedEnumerable<TSource> OrderByWeight<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, int> weighting) where TKey : IComparable
{
    Dictionary<TSource, int> order = new Dictionary<TSource, int>();
    foreach (TSource item in source)
    {
        if (!order.ContainsKey(item)) order.Add(item, weighting(keySelector(item)));
    }
    return source.OrderBy(s => order[s]);
}

You can use it like this:

var data = dt.Select(g => new
{
    Season = g.season,
    AverageTemp = g.temp
}).OrderByWeight(a => a.Season, x =>
{
    if (x == "WINTER") return 1;
    if (x == "SPRING") return 2;
    if (x == "SUMMER") return 3;
    if (x == "AUTUMN") return 4;
    return 99;
});

Source: from my old blog

Upvotes: 0

Eric J.
Eric J.

Reputation: 150108

Assuming you know your weighting function, you could use Linq to Objects:

var sorted = (from o in myList orderby o.SortingValue select o).ToList();

In this example, SortingValue would be a property on the object that encapsulates the attributes in your question and would implement your algorithm.

Sample algorithm for SortingValue:

You could use a Dictionary to hold relevance percentages

Then, your "current parameters" could be used as keys to the Dictionary to get the relevant weighting:

Dictionary<string, double> weightDictionary = // Load somehow

double SortingValue
{
    get {
        double sortingValue;

        foreach(string currentParameter in currentParameters)
        {
            sortingValue += weightDictionary[currentParameter];
        }

        // You could use Math.Random to get a number between say -0.1 and -.1.  
        // Multiply sortingValue by that random number.
        return sortingValue;
    }
}

Upvotes: 2

Related Questions