0

Somewhat similar to this question:

Where do I put the "orderby group.key" in this LINQ statement?

Except I'm using Dynamic.Linq which makes this a bit harder. I have a bunch of data coming from a database and then I'm grouping by some field and then outputing the result. The problem is that the ordering of the groups seems to randomly jump around which isn't very convenient for the end-user. So taking inspiration from the linked question, if I had this:

string[] words = { "boy","car", "apple", "bill", "crow", "brown" };
// note the first non-dynamic select here was just because I don't think dynamic linq 
// will support indexing a string like that and it's not an important detail anyway
var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
                    .GroupBy("new (FirstLetter)","Word");  

foreach(IGrouping<object, dynamic> g in wordList)
{
    Console.WriteLine("Words that being with {0}:",
        g.Key.ToString().ToUpper());
    foreach (var word in g)
        Console.WriteLine("  " + word);
}

Console.ReadLine();

How would I get it to order the keys? At least part of the problem is that the dynamic GroupBy returns an IEnumerable. I thought it might be as easy as:

var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
                    .GroupBy("new (FirstLetter)","Word")
                    .OrderBy("Key"); 

But that gives me a System.ArgumentException (At least one object must implement IComparable.) when it hits the foreach loop.

My actual code in my project is a little more complicated and looks something like this:

var colGroup = row.GroupBy(string.Format("new({0})", 
                           string.Join(",", c)), string.Format("new({0})", 
                           string.Join(",", v)));

Where c is a list of strings that I need to group by and v is a list of strings that I need to select in each group.

Community
  • 1
  • 1
Matt Burland
  • 44,552
  • 18
  • 99
  • 171

2 Answers2

1

Ok - this is one way to do it, but it might be a little to static to be useful. The problem is that I had this part:

.GroupBy("new (FirstLetter)","Word");  

Using new because I can't use a value type as a key (I had another question about that: https://stackoverflow.com/a/26022002/1250301). When with the OrderBy("Key") part, the problem is that it doesn't have a way to compare those dynamic types. I could solve it like this:

var wordList = words.Select(w => new {FirstLetter = w[0].ToString(), Word = w})
                    .GroupBy("FirstLetter","Word")
                    .OrderBy("Key"); 

Making the key a string. Or like this:

var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
                    .GroupBy("new (FirstLetter as k)","Word")
                    .OrderBy("Key.k");

Making it order by something (a char) that is comparable.

I can make it work with my actual problem like this (but it's kind of ugly):

var colGroup = row.GroupBy(string.Format("new({0})", string.Join(",", c)),
                           string.Format("new({0})", string.Join(",", v)))
                  .OrderBy(string.Join(",", c.Select(ob => string.Format("Key.{0}", ob))));
Community
  • 1
  • 1
Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • System.Linq.Dynamic is a very impressive but relatively underused library. Our (non .Net) client- (.Net) server solution would not be possible without this library. Thanks for the question/example – reckface Sep 30 '14 at 08:06
0

I am not sure what you are trying to do, but is that syntax even compiling?

try:

string[] words = { "boy","car", "apple", "bill", "crow", "brown" };

var wordList = words.Select(w => new {FirstLetter = w[0], Word = w})
                    .GroupBy(x => x.FirstLetter, x => x.Word)
                    .OrderBy(x => x.Key); 
Ismail Hawayel
  • 2,167
  • 18
  • 16
  • I'm using dynamic linq. The question isn't to rehash the *exact same question I linked to*. The question is how to do it when the fields to group by and select are passed as strings meaning the whole thing is dynamically typed. – Matt Burland Sep 29 '14 at 20:47