I have below list of items:
ID Date
01200 11/11/2020
01200 11/11/2021
02100 01/01/2019
02100 01/01/2029
I am trying to group items by ID, then for each group select the item which has the Max date, and finally select the item which has the Min date. Taken into account above set of items, the final result would be 11/11/2021.
So I have implemented two ways here to do the same thing. Option 1 is working but option 2 isn't.
step-by-step:
// first get the groups:
var groups = items.GroupBy(i => i.ID);
// find the max date in each group
var maxDates = groups.Select(g => g.OrderByDescending(i => i.Date).First());
// now find the earliest max date
var minDate = maxDates.OrderBy(i => i.Date).First();
combined into one line:
var minDate = items.GroupBy(i => i.ID)
.Select(g => g.OrderByDescending(i => i.Date).First())
.OrderBy(i => i.Date).First();
...
GroupBy(p => p.id,
p => p.date,
(key, g) => new { id = key, date = g.Max() })
returns an IEnumerable of an anonymous type. You cannot convert anonymous type to type Foo via .ToList<Foo>.
You should rewrite you code to resolve compilation error as
var res2 = cv.GroupBy(
p => p.id,
p => p.date,
(key, g) => new Foo{ id = key, date = g.Max() //add here class name Foo
}).Aggregate((u,v) => u.date < v.date ? u: v);
EDIT: or if you not use Dump() to show result then you may use anonymous type in GroupBy() like:
var res2 = cv.GroupBy(
p => p.id,
p => p.date,
(key, g) => new { id = key, date = g.Max() }).Aggregate((u,v) => u.date < v.date ? u: v);
Also you may use #D Stanley idea to find Foo object like:
var minDate = cv.GroupBy(i => i.id,
p => p.date,
(key, g) => new Foo() { id = key, date = g.Max() }).OrderBy(e=>e.date).First();
Related
I am trying to perform Join, GroupBy two columns and select to a new list as
var v = master.Join(
detail,
o => o.Id,
d => d.OrderId,
(o, d) => new
{
DateAdded = o.DateAdded,
VatRate = d.VatRatePercentage,
InvoiceDescription = o.InvoiceDescription
}).GroupBy(c => new
{
c.DateAdded,
c.VatRate
})
.Select(gcs => new
{
DateAdded = gcs.Key.DateAdded.Date,
VatRate = gcs.Key.VatRate,
InvoiceTypeDescription = gcs.Key.InvoiceDescription,
}
).ToList();
but i get the error
'<anonymous type: DateTime DateAdded, decimal VatRate>' does not contain a definition for 'InvoiceTypeDescription' and no accessible extension method 'InvoiceTypeDescription' accepting a first argument of type '<anonymous type: DateTime DateAdded, decimal VatRate>' could be found
I would like to group by two columns (DateAdded, VatRate) but get the InvoiceDescription column also in the results. How can i fix that?
This is a sample:
var resultmutiplekeylambaorderbyelement = studentlist
.GroupBy(stu => new{stu.standard, stu.age})
.OrderBy(g => g.Key.standard).ThenBy(y=> y.Key.age)
.Select(g => new { standardkey = g.Key.standard, agekey = g.Key.age, studentobj = g.OrderBy(y => y.name) });
I have a list of guids as string:
This is how i retrive my list of string guids:
List<string> p0 = ctx.PrProjectRating.Select(k => k).GroupBy(g => new { g.PrPIdG }, (key, group) => new { sumR = group.Sum(k => k.PrValue), pidG = key.PrPIdG }).Select(t => t.pidG).ToList();
Now i have another list that contains a field called pidG but this list needs to be ordered by the list of guid strings above.
How do i achiveve this.
i tried:
List<PProject> p = p.OrderBy(c => p0.Contains(c.PIdG)).ToList();
but still the list is not ordered by the string guids in the first list "p0"
You have to do join here
List<string> p0 = ctx.PrProjectRating
.Select(k => k)
.GroupBy(g => new { g.PrPIdG }, (key, group) =>
new { sumR = group.Sum(k => k.PrValue), pidG = key.PrPIdG })
.Select(t => t.pidG).ToList();
var result = p0.Join(p, x => x, c => c.PIdG, (x, c) => c)
.ToList()
I want to filter a group of documents by Year, Format and Content.
n pseudo-SQL:
SELECT * FROM /test/document
WHERE
((format=f1|| format=f2||...|| format=fn) AND
(Year!=2013 AND Year!=2015) AND
(content like %c1% || content like %c2% ||...|| content like %cn%))
As you see, the number of formats and content items are dynamic and will be chosen by user.
So far, I figured out how to make dynamic query for each field separately and then combine them using bool query like the code below;
// For YEAR
QueryContainer qYear=null;
foreach (var year in years)
{
qYear |= new TermQuery() { Field = "year", Value = year };
}
// For FORMAT
var qformat = new List<QueryContainer>();
foreach (var format in txtDocs)
{
qformat.Add(Query<Document>.Match(m => m.OnField(p => p.Format).Query(format)));
}
// For CONTENT
var qc = new List<QueryContainer>();
qc.Add(Query<Document>.Match(m => m.OnField(p => p.File).Query(discpString).Boost(2)));
qc.Add(Query<Document>.Match(m => m.OnField(p => p.File).Query(roleString)));
qc.Add(Query<Document>.Match(m => m.OnField(p => p.File).Query(taskString)));
qc.Add(Query<Document>.Match(m => m.OnField(p => p.File).Query(sysString).Boost(2)));
//MY QUERY
var searchResults = client.Search<Document>(s => s.Fields(f => f.Title, f => f.Format, f => f.Year, f => f.DateCreated, f => f.Id, f => f.Path, f => f.Size, f => f.Firstwords).
Index(defaultIndex).From(0).Size(100).
Query(q => q.Bool(b => b.MustNot(qYear).Should(qformat.ToArray()).Should(qc.ToArray()))));
When I run this code, the results for year and content field is what I expect but other formats that are not in the filtered list are also included! I want it to just retrieve those documents with the selected formats.
Does anyone knows where is my mistake?
I could find where was my mistake!
I used Querycontainer for format in the same command as what I used for Year and then used Must in my query. Here is the changed part of the code:
// For FORMAT
QueryContainer qF=null;
foreach (var format in txtDocs)
{
qF |= new TermQuery()
{
Field = "format",
Value = format
};
}
//MY QUERY
var searchResults = client.Search<Document>(s => s
.Fields(
f => f.Title,
f => f.Format,
f => f.Year,
f => f.DateCreated,
f => f.Id,
f => f.Path,
f => f.Size,
f => f.Firstwords)
.Index(defaultIndex)
.From(0)
.Size(100)
.Query(q => q
.Bool(b => b.MustNot(qYear)
.Must(qF)
.Should(qc.ToArray())
)
);
How can I transform this SQL query to LINQ?
SELECT eg.Name Name, sum(bi.PlannedAmount) Amount
FROM BudgetItem bi, Expense e, ExpenseGroup eg
WHERE Discriminator = 'ExpenseItem' AND
bi.ExpenseId = e.Id AND
e.ExpenseGroupId = eg.id AND
bi.MonthlyBudgetId = 1
GROUP BY eg.Name
So far I've come up with this line:
var result = context
.ExpenseGroups
.GroupBy(eg => eg.Id, (s) => new { Name = s.Name, Amount = s.Expenses.SelectMany(e => e.Items).Sum(i => i.PlannedAmount) })
.ToList();
But I still cannot figure out what expression to use to add 'bi.MonthlyBudgetItem = 1'.
Does anybody have an Idea?
Edit #1:
I forgot to mention the relationships between the entities. Every ExpenseGroup has many Expenses, and every Expense has many BudgetItems.
So, ExpenseGroup => Expenses => BudgetItems
Edit #2:
I'm using Entity Framework and every ExpenseGroup has a Collection of Expense objects (every Expense has a ExpenseGroup object), as well as every Expense has a Collection of BudgetItem objects (every BudgetItem object has a Expense object).
I suppose something like this should do it:
var result = context
.ExpenseGroups
.Where(x => x.Discriminator == 'ExpenseItem' &&
x.bi.ExpenseId == e.Id &&
x.e.ExpenseGroupId == eg.id &&
x.bi.MonthlyBudgetId == 1)
.GroupBy(eg => eg.Id, (s) => new { Name = s.Name, Amount = s.Expenses.SelectMany(e => e.Items).Sum(i => i.PlannedAmount) })
.ToList();
Something similar to this...
var result = (from g in context.ExpenseGroups
where g.Expense.BudgetItem.MonthlyBudgetId == 1
select g)
.GroupBy(eg => eg.Id, (s) => new { Name = s.Name, Amount = s.Expenses.SelectMany(e => e.Items).Sum(i => i.PlannedAmount) })
.ToList();
or
var result = context.ExpenseGroups
.Where(g => g.Expense.BudgetItem.MonthlyBudgetId == 1)
.GroupBy(eg => eg.Id, (s) => new { Name = s.Name, Amount = s.Expenses.SelectMany(e => e.Items).Sum(i => i.PlannedAmount) })
.ToList();
You are actually doing an inner join in your SQL query, so do similarly in your linq query as well. This should work:-
var result = from bi in context.BudgetItem
join e in context.Expense
on bi.ExpenseId equals e.Id
where bi.MonthlyBudgetId == 1
join eg in ExpenseGroup
on e.ExpenseGroupId equals eg.id
group new { bi, eg } by eg.Name into g
select new
{
Name = g.Key,
Amount = g.Sum(x => x.bi.PlannedAmount)
};
I have a query like below. I want to group my values by "RapId"
Result must be come like this:
RaporId 1, List of UserId 15,24,23
RaporId 2, List of UserId 18,45,57
var sorgu = (from ra in Model1
join me in Model2
on ra.RapId equals me.RapId
select new
{
RapId = ra.RapId,
UserId= ra.RaportorId,
})
.GroupBy(x=>x.RapId )
.SelectMany(x => x)
.ToList();
var results = sorgu.GroupBy(p => p.RapId , p => p.UserId,
(key, g) => new { RapId = key, UserId= g.ToList() });
I get an error like this
> Error 39 Cannot convert lambda expression to type
> 'System.Collections.Generic.IEqualityComparer<AnonymousType#1>'
> because it is not a delegate type
What's wrong with this query?
Compiler thinks you are trying to use this overload: But you are passing a lambda expressions instead of IEqualityComparer.I think you just need to remove p => p.UserId :
var results = sorgu.GroupBy(p => p.RapId,
(key, g) => new { RapId = key, UserId= g.ToList() });