views:

169

answers:

3

According to this site the ordering algorithm for hacker news goes something like this:

(p - 1) / (t + 2)^1.5

Description:

Votes divided by age factor

p = votes (points) from users. t = time since submission in hours.

p is subtracted by 1 to negate submitters vote. age factor is (time since submission in hours plus two) to the power of 1.5.

Given a table structure similar to this:

Item
ID
Link
DatePosted

Item_Votes
ItemID
Value

What would be the best way to implement the algorithm using linq to sql, would I be able to write the query entirely in linq or would I need to use a stored procedure or something else.

Update. Ended up using the code below based off TJB's answer:

    var votesQuery =
        from i in db.Items
        join v in db.Item_Votes on i.ItemID equals v.ItemID
        orderby
            (double)(v.Value - 1) /
                    Math.Pow(
                        (DateTime.Now - i.DatePosted.Value).TotalHours + 2,
                    1.5) descending
        select i;
+1  A: 

Use a Comparer. This will allow you to write the logic for the comparisons between rows any way you want.

Here is an example, using case-insensitive ordering:

public void LinqExample()
{
    string[] words = { 
        "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" 
    };

    var sortedWords = words.OrderBy(a => a, new CaseInsensitiveComparer());

    ObjectDumper.Write(sortedWords);
}

public class CaseInsensitiveComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return string.Compare(x, y, StringComparison.OrdinalIgnoreCase);
    }
}

http://msdn.microsoft.com/en-us/vcsharp/aa336756.aspx

Robert Harvey
+1  A: 

This might work (untested):

var orderedList = 
    from extracted in (
         from i in unorderedList 
             select new 
             { 
                 Item = i,
                 Order = (p - 1) / Math.Pow(t + 2, 1.5)
             }
             orderby extracted.Order
             select extracted.Item
         ).ToList();
Robert Harvey
+4  A: 

Using 2 1 Linq queries (there's probably still a more efficent way)

var votesQuery =
    from i in items
    join v in votes on i.Id equals v.ItemId
    orderby
        (v.Value - 1) / 
                Math.Pow( 
                    (DateTime.Now - i.Posted).Add(new TimeSpan(2,0,0)).Hours, 
                1.5 )
    select new
    {
        Item = i,
        Vote = v
    };
TJB
This is fun code to write, I think I kinda miss math...I mean *ANY* math...
TJB
thanks mate using something very similar to this and its working well
Luke Lowrey
Glad to hear! Working code is good code.
TJB