0

Below is my code , i am trying to get distinct sub keys in descending order All is well but in OrderByDescending it is not suggesting field

 List<string> Sub_key_list = dt
   .AsEnumerable()
   .Select(d => d.Field<string>("Sub_Key_Name"))
   .Distinct()
   .OrderByDescending(e => e.not suggesting field here )
   .ToList();

Am i writing it wrong ?

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • 3
    Why would it suggest a field? You're getting a distinct sequence of strings... what "field" do you expect to be suggested? `Length`, perhaps? – Jon Skeet May 16 '17 at 07:26
  • 3
    I suspect all you need is `e => e`.... – Marc Gravell May 16 '17 at 07:28
  • you have already selected `Sub_Key_Name` from `dt` and there is no other field available to be suggested in `orderByDescending`. – Abi May 16 '17 at 07:33
  • @Abi Well, you could of course order by the length of the string, for example. – Patrick Hofman May 16 '17 at 07:33
  • yeah.. that's correct.. :) @PatrickHofman – Abi May 16 '17 at 07:37
  • Bottom line: you seem to be asking why Intellisense doesn't propose any type member when you type the `.` after the `e`. I don't see anything in your little code snippet that would explain that. You ought to get all the various `System.String` members at that point. You'll need to provide better information, including a good [mcve] that reliably reproduces the problem. – Peter Duniho May 16 '17 at 07:39
  • 2
    @PeterDuniho OP is expecting the same intellisense behavior like two rows above where he select a field from a datatable - but at that point there is no more datatable, just string ;o) – Sir Rufo May 16 '17 at 07:42
  • @SirRufo: hmmm...okay. If that's the case, then I don't think that just selecting the `string` value is going to solve the OP's question, otherwise he wouldn't have been looking for the `Field()` method again. Based the assumption that you've correctly inferred their intent, I've added an answer that I think is more likely to address the question. – Peter Duniho May 16 '17 at 08:34
  • @PeterDuniho Thanks , Purpose was to get descending ordered distinct value , maybe I am still explaining it wrong . That''s why everybody spent all their forces on intellisense behavior . –  May 16 '17 at 10:30
  • _"maybe I am still explaining it wrong"_ -- if all you want is the `"Sub_Key_Name"` field, without duplicates, in descending order, then there should be no need for any "field" in the `OrderByDescending()` lambda expression. So, yes...I'd say if that's the case, you're not explaining yourself very well. See [ask] for information on how to present your question in a clear answerable way. Note that it's very important to have a clear, precise, and detailed problem statement, including a statement of what the code does now and what you want it to do instead. – Peter Duniho May 16 '17 at 15:07
  • @PeterDuniho aaye aaye peter , I checked and come to know what should we include while asking a question . Thanks a lot –  May 17 '17 at 04:14

3 Answers3

3

The argument passed to OrderByDescending is an IEnumerable<string>, so e is your string here. That means you can simply order by e like this:

.OrderByDescending(e => e)
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
0

According to one comment:

OP is expecting the same intellisense behavior like two rows above where he select a field from a datatable - but at that point there is no more datatable, just string

That is, you want to be able to order by some field in your data row other than the one you are selecting for the Distinct() operation. I think that gets a little complicated, but it's doable.

Unfortunately, the Distinct() method returns an unordered sequence. I.e. you can't do your ordering first and then use Distinct(). This prevents us from being able to extract into an anonymous type the fields we care about for ordering and the final value, ordering that data, and then using Distinct() on the result.

On the other hand, without a custom equality comparer implementation, Distinct() will apply its logic to the entire object, rather than just one field (there's not an overload that lets you select a value for the operation). So we would need to provide a custom equality comparer, which is still doable with anonymous types, but gets even more complicated.

There is also a logical issue: the Distinct() operation necessarily will reduce several rows with the same value into just one. This results in there just being one ordering field value, from the potentially many that were there, but you don't get to pick which one.

Fortunately, all of the above can be addressed using GroupBy() instead of Distinct(). With GroupBy(), you can initially select an anonymous type containing the fields of interest, then group them by a specific key (the "Sub_Key_Name" value in this case), but without losing any of the ordering fields. You can then pick from the ordering fields using whatever logic makes sense in your application (your question doesn't specify, so for this example, I just use the maximum value), and use that value to actually order the results. Finally, selecting just the grouping key gets you the final value you wanted.

That would look something like this:

List<string> Sub_key_list = dt
   .AsEnumerable()
   .Select(d => new
   {
       OrderKey = d.Field<int>("OrderKey"), // i.e. whatever you want here
       Value = d.Field<string>("Value"),
   })
   .GroupBy(e => e.Value)
   .OrderByDescending(e => e.Max(x => x.OrderKey)) // I used Max...use whatever you want
   .Select(e => e.Key)
   .ToList();


For additional inspiration, see also related/similar questions:
Linq orderby and distinct
Select Multiple Fields from List in Linq
Distinct in Linq based on only one field of the table

Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
0

First of all i doubt if it works d.Field("Sub_Key_Name") ?

I create a simple example of list of strings and then sorting :

var list = new List<string>();
        list.Add("a");
        list.Add("ab");
        list.Add("ab");
        list.Add("abc");
        list.Add("lmn");
        list.Add("xyz");

        var q = list.AsEnumerable().Select(s => s).Distinct().OrderByDescending(s => s).ToList();

        foreach(var i in q)
        {
            Console.WriteLine(i);
        }

It works fine.

Sonu
  • 25
  • 8
  • _"i doubt if it works"_ -- why do you say that? The code the OP shows works fine, assuming you start with a `DataTable` object for the `dt` variable (which seems like a same assumption), and as long as there is in fact a `"Sub_Key_Name"` column in that table. – Peter Duniho May 16 '17 at 15:08