From this LINQ:
var inspectionItems = inspArchive.Select(x => x.InspectionItems);
I get this result in inspectionItems :
My question is how can I make using LINQ in elegant way to make from inspectionItems result above one array distincted by Id.
Like that:
You want the SelectMany() LINQ method:
var inspectionItems = inspArchive.SelectMany(x => x.InspectionItems);
If you only want distinct items by a particular property, then you can either implement an equality comparer to see if your inspection classes are equal, then call .Distinct(myInspectionEqualityComparer) at the end of your method chain, or you can do this:
var distinctInspectionItems = inspArchive.SelectMany(x => x.InspectionItems)
.GroupBy(i => i.Id)
.Select(group => group.First());
Without seeing more of your code, I think you want to use SelectMany and Distinct ?
var inspectionItems = inspArchive.SelectMany(x => x.InspectionItems).Distinct();
The question is unclear, but check if this works for you:
var inspectionItems = inspArchive.SelectMany(x => x.InspectionItems)
.GroupBy(x => x.ID)
.Select(g => g.First())
.ToArray();
Related
I cannot seem to combine 2 GroupBy statements in 1 linq expression..
For now i'm doing something like this:
double maxInvestment = 0;
foreach (var playerAction in TotalUserActions.GroupBy(p => p.Player))
{
var MaxInvestmentPerPlayer = playerAction.GroupBy(p => p.RoundId)
.Select(p => p.LastOrDefault())
.Sum(p=> p.BetSize);
if(MaxInvestmentPerPlayer > maxInvestment)
maxInvestment = MaxInvestmentPerPlayer;
}
What I would like to do is something like this...
double maxInvestment = TotalUserActions.GroupBy(p => p.Player)
.GroupBy(p => p.RoundId)
.Select(p => p.LastOrDefault())
.Sum(p=> p.BetSize);
But that wont work.. Can someone help me on this?
Thanks!
Looks like this is what you want, the key takeaway being the inner query is wrapped in an outer call to Select():
var maxInvestment = TotalUserActions.GroupBy(p => p.Player)
.Select(g => g.GroupBy(x => x.RoundId)
.Select(x => x.LastOrDefault())
.Sum(x => x.BetSize))
.Max();
I do question your use of LastOrDefault() though as, since you have not specified any ordering, you may as well use FirstOrDefault() and save the hassle of skipping to the last element.
I have three tables, car_type, car_manufacturer and car_model. When the user click on the particular vehicle type they want to browse, I'd like to show them a list of available manufacturers. The problem is the list of manufacturers is not distinct or unique. So if my db has three models from Mazda, Mazda will show up on the list 3 times. This is my controller:
public ActionResult Browse(string click_string)
{
var x = carDB.Models
.Include(b => b.Manufacturer)
.Include(a => a.VehicleType)
.Where(a => a.VehicleType.TypeName == click_string);
return View(x.ToList());
}
How can I write this to remove redundant listings? This is all new to me, so go easy on me.
You have to query for Manufacturers, not for Vehicles:
var x = carDB.Models.Where(a => a.VehicleType.TypeName == click_string)
.Select(a => a.Manufacturer)
.Distinct();
It usually works well to try and avoid Distinct altogether. You want manufacturers? Get manufacturers. And determine from there which ones you need: the ones that produce models that have click_string in their type name:
carDB.Manufacturers.Where(manufacturer => manufacturer.Models
.Any(model => model.VehicleType.TypeName == click_string))
You may want to include Models and/or VehicleType, that depends on what you want to show in the view.
First try doing a .Distinct() at the end of the query, if it does not work you might need to provide a custom comparer for the .Distinct()
You should be able to use .Distinct to return the distinct elements.
var x = carDB.Models
.Include(b => b.Manufacturer)
.Include(a => a.VehicleType)
.Where(a => a.VehicleType.TypeName == click_string)
.Distinct();
add distinct
var x = carDB.Models
.Include(b => b.Manufacturer)
.Include(a => a.VehicleType)
.Where(a => a.VehicleType.TypeName == click_string)
.Select(y => y)
.Distinct();
The .Select() might be a bit verbose but without trying it in my visual studio i put it in there for saftey
This is the query I am trying to do.
var commentActivity = project.ProjectDoc
.Select(c => c.Comment.Select(i => i.UserID))
.Distinct()
.Count();
What I want is the number of comments from distinct users on a specific project, but ANY ProjectDoc. This query "works" the result is just wrong. The model is like this, generically sketched.
Project
ProjectDoc
Comment
Update: I had to go one level deeper, based on the answer below I tried a few things that didn't work so I though I would post this as a reference. Note the two SelectMany methods.
var replyActivity = project.ProjectDoc
.SelectMany(c => c.Comment.SelectMany(r => r.CommentReply.Select(u => u.UserID)))
.Distinct()
.Count();
Use SelectMany instead of Select
project.ProjectDoc
.SelectMany(c => c.Comment.Select(i => i.UserID))
.Distinct()
.Count()
var data = (from con in project.ProjectDoc
select new
{
CommentCount=project.Comment.Count(x=>x.UserID==con.UserID)
}).ToList();
i think this will help you.
How do I order the following? The orderBy doesnt recognise the x.Name.
var xRefsNames = db.CrossRefs.Where(x => pgNos.Contains(x.PG))
.Select(x => x.Name)
.Distinct()
.OrderBy(x=>x.Name);
Your select is projecting a different object, probably a string based on the name. You want to just order by x.
var xRefsNames = db.CrossRefs.Where(x => pgNos.Contains(x.PG))
.Select(x => x.Name)
.Distinct()
.OrderBy(x=>x);
hi I have the following code and would like to only make each union if a condition is true.
I Know I could write a select of if else but wanted to know if there is a slicker Linq way!?
//join the list into one and sort by seqnumber
SegmentList = Alist.Cast<BaseSegment>()
.Union(BList.Cast<BaseSegment>()).Union(CList.Cast<BaseSegment>())
.OrderBy(item => item.SegSeqNumber).ToList();
So given the above if ATest =true how do I only iclude Alist like wise if BTest && CTest are true how do I include only BList and Clist
Thanks
To do it in a LINQ style way with your checkboxes, something like:
SegmentList = Alist.Where(i => checkbox1.IsChecked).Cast<BaseSegment>()
.Union(BList.Where(i => checkbox2.IsChecked).Cast<BaseSegment>())
.Union(CList.Where(i => checkbox3.IsChecked).Cast<BaseSegment>())
.OrderBy(item => item.SegSeqNumber).ToList();
would work. But I don't think it is either very understandable or efficient.
Something like this?
SegmentList = Alist.Cast<BaseSegment>()
.Union(includeB ? BList.Cast<BaseSegment>() : Enumerable.Empty<BaseSegment>())
.Union(includeC ? CList.Cast<BaseSegment>() : Enumerable.Empty<BaseSegment>())
.OrderBy(item => item.SegSeqNumber)
.ToList();
This is not identical to your original (it will remove duplicates from Alist no matter what) but should be what you want.
For any more than 2 conditional unions, you would probably want a different query, something like:
var listsByCb = new Dictionary<CheckBox, MyListType>
{{ aListBox, aList}, {bListBox, bList}, {cListBox, cList}};
var segmentList = listsByCb.Where(kvp => kvp.Key.Checked)
.SelectMany(kvp => kvp.Value.Cast<BaseSegment>())
.Distinct();
.OrderBy(item => item.SegSeqNumber)
.ToList();
try something like
SegmentList = Alist.Cast<BaseSegment>().Where(z=>ATest)
.Union(BList.Cast<BaseSegment>().Where(x=>Btest)).Union(CList.Cast<BaseSegment>().Where(c=>Ctest))
.OrderBy(item => item.SegSeqNumber).ToList();
where class in each case will return all elements if corresponding test is true and will return no element otherwise. its completely untested though
Use a Where() clause for that, like following:
//join the list into one and sort by seqnumber
SegmentList =
Alist.Cast<BaseSegment>().Where(a => ATest(a))
.Union(
BList.Cast<BaseSegment>(.Where(b => BTest(b))
.Union(CList.Cast<BaseSegment>().Where(c => CTest(c))
.OrderBy(item => item.SegSeqNumber).ToList();
By the way, do you really need the last ToList()?