Question

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.

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;
    }
}
Was it helpful?

Solution

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;

OTHER TIPS

    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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top