dhardy
dhardy

Reputation: 1003

LINQ contains query custom ordering

I have a LINQ query that gets me all results where the code is contained within a list. This works fine, however I need to keep the order as per the list of codes. So when the EnumerableRowCollection is returned, the rows are in the same order as tehy were in the List.

Here's my current code:

if (productcodes != "")
{
    string[] pcodes = productcodes.Split('|');

    // Get most recently viewed first
    Array.Reverse(pcodes);

    List<int> prodCodes = new List<int>();

    foreach (string pc in pcodes)
    {
        if (pc != "")
        {
            prodCodes.Add(Convert.ToInt32(pc));
        }
    }

    results = results.Where(d => d["ProductCode"] != DBNull.Value && (int)d["ID"] > 0 && prodCodes.Contains((int)d["ProductCode"])).Select(d => d);
}

So I need the EnumerableRowCollection results to be ordered the same as they are in List prodCodes rather than it's own random order.

Any ideas?

Upvotes: 2

Views: 368

Answers (2)

Amy B
Amy B

Reputation: 110101

Assuming the prodCodes are unique, you can project them into a mapping:

Dictionary<int, int> orderMap = prodCodes
  .Select( (val, i) => new {val, i} )
  .ToDictionary(x => x.val, x => x.i);

Then you can use the orderMap to order the result:

var results = GetSomeResults();
results = results.OrderBy(row => orderMap[(int)row["ProductCode"]]);

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460098

This is all you need:

IEnumerable<int> pcodes = productcodes.Split('|')
   .Where(s => !string.IsNullOrWhiteSpace(s))
   .Select(s => int.Parse(s))
   .Reverse();

var result = from code in pcodes
             join row in results on code equals row.Field<int>("ProductCode")
             select row;

The join at the end is in the order of the first sequence(the pcodes) and only containing ProductCodes are joined on an "inner join".

Upvotes: 3

Related Questions