tags:

views:

598

answers:

2

Hi - I'm trying to create a collection of strings in an order defined by another array. Sounds confusing I know so let me explain

requiredOrderOfElements{
[0] category1,
[1] categoryX,
[2] something else
}

my client passes up a string array containing the key and value ie

passed from client {
[0][0] categoryX,
[0][1] value from Category X,
[1][0] something else,
[1][1] value for something else,
[2][0] category1,
[2][1] value from Category 1
}

what I want, is the "value" texts in the required order of the keys

what I want
[0]value from Category 1
[1]value from Category X
[2]value for something else

I've looked at OrderBy / IComparer and can't see an obvious way to implement what I need. My current solution is an ugly nested for-loop

Any ideas for a more elegant way would be appreciated

kind regards

G

Update: - here is the test

[TestFixture]
public class GL_Linq_Test
{
    [Test]
    public void CanOrderByAnotherArray()
    {
        var requiredOrder=new[]{"my","required","order"};
        var passedFromClient = new[]
                                   {
                                       new[] {"required", "cat"},
                                       new[] {"order", "dog"},
                                       new[] {"my", "bird"}
                                   };

        var ordered = FunkyOrderer.Order(requiredOrder, passedFromClient);

        Assert.That(ordered.First()[1],Is.EqualTo("bird"));
        Assert.That(ordered.Skip(1).First()[1], Is.EqualTo("cat"));
        Assert.That(ordered.Skip(2).First()[1], Is.EqualTo("dog"));
    }
}

public static class FunkyOrderer
{
//returns order bird,dog,cat not bird,cat,dog        
public static IEnumerable<string[]> Order(string[] requiredOrder, IEnumerable<string[]>passedFromClient)
    {
        return from o in requiredOrder
                     join f in passedFromClient on o equals f[0]
                     orderby o
                     select f;
    }
}
A: 
    var orderByThese = new string[] { "category1", "categoryX", "something else" };

    var fromClient = new string[][] 
    {
        new string[] { "categoryX", "value from Category X" },
        new string[] { "something else", "value for something else" },
        new string[] { "category1", "value from Category 1" }
    };

    var joined = from o in orderByThese
                 join f in fromClient on o equals f[0]
                 orderby o
                 select f;
Matthew Whited
not quite - gets the first item in the array correctly but the other two are the wrong way around. I'll post a test
Gilly
+1  A: 

The problem is that you assuming an array of strings will be ordered by their index (they won't). The order of "my", "order", "required" is correct using the built in string comparer. The easiest solution is to modify your LINQ query to take the index into account when ordering.

return from o in requiredOrder.Select((o, i) => new { Value = o, Index = i })
       join f in passedFromClient on o.Value equals f[0]
       orderby o.Index
       select f;
Samuel
awesome - thanks a lot.
Gilly