How to order a LinQ result set created by a list of ID and order it use existing order of the list - linq

My code is something like this:
List<int> IDs = new List<int> {9,7,38, 23}
IQueryable<Post> pp = myDataEntity.Posts.Where(p=>IDs.Contains(p.ID));
How can I explain that I want to sort pp by the order of ID in the IDs? Thank you.

You can order by List.IndexOf:
IQueryable<Post> orderedPosts myDataEntity.Posts
.Select(p => new { Post=p, Index=IDs.IndexOf(p.ID) })
.Where(x => x.Index >= 0)
.OrderBy(x => x.Index)
.Select(x => x.Post);

Assuming you want to keep the order of ID you have in IDs and not actually the ordered verison of it, this is how you can do it:
var pp = IDs.Select(x=> myDataEntity.Posts.Where(p=>p.ID == x))
.SelectMany(x=>x);
Using IDs as your external collection, you get to keep the ordering of the elements in it.

use OrderByDescending
IQueryable<Post> pp = myDataEntity.Posts.Where(p=>IDs.Contains(p.ID))
.OrderByDescending(p => p.ID)

Related

Is there a easy way to filter out unique elements using linq?

I have an xml document
<NumSet>
<num>1</num>
<num>2</num>
<num>2</num>
<num>3</num>
</NumSet>
I want unique elements shown up, ie 1 and 3. not distinct which will also bring out 2.
How to do that? Do I have to use Group? Is there any concise way to do that?
You are right, you can use GroupBy and filter group which has only one item by using Count() == 1:
var output = XDocument.Load(xmlFile)
.Descendants("num")
.Select(e => e.Value)
.GroupBy(x => x)
.Where(g => g.Count() == 1)
.Select(g => g.Key);
It sounds like you want a Distinct GroupBy query... Take a look at the Need help on Linq with group by and distinct post here on StackOverflow.
XElement xe = XElement.Parse(#"<NumSet><num>1</num><num>2</num><num>2</num><num>3</num></NumSet>");
var query = xe.Elements("num")
.GroupBy(x => x.Value)
.Where(x=>x.Count ()==1)
.Select (x => x);
To do what you need I'd say that yes, you need to use GrouBy, and then count the elements in each group, and return those that contains just one element. In code, this translates to:
var query = lst.GroupBy(x => x)
.Where(x => x.Count() == 1)
.Select(x => x.Key);

Finding n-Most Popular Using Linq

How should I structure a Linq query to return a List or Ienumerable of the most popular Tags in my db (I am using EF4.1 by the way).
Currently I have:
var tagsListing = db.Tags
.GroupBy(q => q.Name)
.OrderByDescending(gp => gp.Count())
.Take(5)
.Select();
I think I am part of the way there, but I am unsure of how to structure the Select statement...
Your Select call could look like this:
.Select(gp => gp.Key)
That will give you an IEnumerable<string> of your most popular tags (assuming that Name is a string).
Assuming you want the name and the count, just:
.Select(g => new { Name = g.Key, Count = g.Count() });
EDIT: If you want the complete tags as well, you could use:
.Select(g => new { Tags = g, Count = g.Count() })
which would give you a sequence of groups of tags, all with the same name within a group. Or you might only want the first tag within each group, e.g.
.Select(g => g.First())
It's not clear what a Tag consists of, or what exactly you want in the results.
You've written a perfectly workable query and do not need to call .Select
IQueryable<IGrouping<string, Tag>> tagsListing = db.Tags
.GroupBy(q => q.Name)
.OrderByDescending(gp => gp.Count())
.Take(5);
List<IGrouping<string, Tag>> results = tagListing.ToList();
You probably want to select the names like this:
.Select(gp => gp.Key);

LINQ Group By into a Dictionary Object

I am trying to use LINQ to create a Dictionary<string, List<CustomObject>> from a List<CustomObject>. I can get this to work using "var", but I don't want to use anonymous types. Here is what I have
var x = (from CustomObject o in ListOfCustomObjects
group o by o.PropertyName into t
select t.ToList());
I have also tried using Cast<>() from the LINQ library once I have x, but I get compile problems to the effect of it being an invalid cast.
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
.GroupBy(o => o.PropertyName)
.ToDictionary(g => g.Key, g => g.ToList());
I cannot comment on #Michael Blackburn, but I guess you got the downvote because the GroupBy is not necessary in this case.
Use it like:
var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]
Additionally, I've seen this perform way better than when using GroupBy().ToDictionary().
For #atari2600, this is what the answer would look like using ToLookup in lambda syntax:
var x = listOfCustomObjects
.GroupBy(o => o.PropertyName)
.ToLookup(customObject => customObject);
Basically, it takes the IGrouping and materializes it for you into a dictionary of lists, with the values of PropertyName as the key.
This might help you if you to Get a Count of words. if you want a key and a list of items just modify the code to have the value be group.ToList()
var s1 = "the best italian resturant enjoy the best pasta";
var D1Count = s1.ToLower().Split(' ').GroupBy(e => e).Select(group => new { key = group.Key, value = group.Count() }).ToDictionary(e => e.key, z => z.value);
//show the results
Console.WriteLine(D1Count["the"]);
foreach (var item in D1Count)
{
Console.WriteLine(item.Key +" "+ item.Value);
}
The following worked for me.
var temp = ctx.Set<DbTable>()
.GroupBy(g => new { g.id })
.ToDictionary(d => d.Key.id);

Find the max value in a grouped list using Linq

I have a linq expression that returns transactions in groups. Each transaction has a numerical value and I now need to know what is the highest value from all the transactions returned. This value is held in a field called TransactionId
Here is the expression I am using to get the grouped list.
var transactions = ctx.MyTransactions
.Where (x => x.AdapterId == Id)
.GroupBy(x => x.DeviceTypeId);
I now need to write an expression that works on the “transactions” grouped list to find the “max” of the TransactionId field. I’ve tried different ideas but none seem to work with the grouped results. I’m new to linq so I’m not sure how to do this.
Have you tried finding the maximum in each group and then finding the maximum of that over all groups?
int max = transactions.Max(g => g.Max(t => t.TransactionId));
Or you could just query the database again:
int max = ctx.MyTransactions
.Where(x => x.AdapterId == Id)
.Max(t => t.TransactionId);
This will give you the max in each group
var transactionIds = ctx.MyTransactions
.Where (x => x.AdapterId == Id)
.GroupBy(x => x.DeviceTypeId,
g => new {
DeviceTypeId = g.Key,
MaxTransaction = g.Max(x => x.TransactionId)
});

OrderBy descending in Lambda expression?

I know in normal Linq grammar, orderby xxx descending is very easy, but how do I do this in Lambda expression?
As Brannon says, it's OrderByDescending and ThenByDescending:
var query = from person in people
orderby person.Name descending, person.Age descending
select person.Name;
is equivalent to:
var query = people.OrderByDescending(person => person.Name)
.ThenByDescending(person => person.Age)
.Select(person => person.Name);
Use System.Linq.Enumerable.OrderByDescending()?
For example:
var items = someEnumerable.OrderByDescending();
Try this:
List<int> list = new List<int>();
list.Add(1);
list.Add(5);
list.Add(4);
list.Add(3);
list.Add(2);
foreach (var item in list.OrderByDescending(x => x))
{
Console.WriteLine(item);
}
Try this another way:
var qry = Employees
.OrderByDescending (s => s.EmpFName)
.ThenBy (s => s.Address)
.Select (s => s.EmpCode);
Queryable.ThenBy
This only works in situations where you have a numeric field, but you can put a minus sign in front of the field name like so:
reportingNameGroups = reportingNameGroups.OrderBy(x=> - x.GroupNodeId);
However this works a little bit different than OrderByDescending when you have are running it on an int? or double? or decimal? fields.
What will happen is on OrderByDescending the nulls will be at the end, vs with this method the nulls will be at the beginning. Which is useful if you want to shuffle nulls around without splitting data into pieces and splicing it later.
LastOrDefault() is usually not working but with the Tolist() it will work. There is no need to use OrderByDescending use Tolist() like this.
GroupBy(p => p.Nws_ID).ToList().LastOrDefault();

Resources