My data is such as
A12
12B
333
CC4
How can i select the records provided from a char array?
var c = new char[] {'A','B','C'};
Something like the following
var result = context.data.Where(x => x.SerialNo.Contains(c)).ToList();
In the test case above the result should be equal to
A12
12B
CC4
since A is available in first line, B on second and C on the last line
var result = context.data
.Where(x => x.SerialNo.Any(l => c.Contains(l)))
.ToList();
Related
I have a collection, for example:
**id1, id2, value**
1 9 12
2 9 6
3 11 8
4 11 87
I want to use LINQ and get the following result:
**value**
6
87
P.S.
id1 - select MAX;
id2 - group column;
I need an answer in the form of
var result = list.GroupBy(x=>x.id2).select(s=>s.value);
I hope for your help.
EDIT: Okay, now we've got a slightly clearer set of requirements (though still far from clearly written) the simplest approach would probably be:
var maxes = list.GroupBy(x => x.id2,
(key, xs) => xs.OrderByDescending(x => x.id1)
.First()
.value);
Unfortunately LINQ doesn't provide a simple way of getting "the element with the maximal value" (instead of the maximal value itself). I have a method in MoreLINQ which does this though, called MaxBy:
var maxes = list.GroupBy(x => x.id2,
(key, xs) => xs.MaxBy(x => x.id2).value);
Original answer (Grouping by id2, taking the maximum value)
I'm answering assuming you actually meant to group by id2 rather than id1, and you actually wanted the results of 12 and 87 rather than 6 and 87. In that case, you'd want:
var maxes = list.GroupBy(x => x.id2, (id, xs) => xs.Max(x => x.value));
Or (possibly simpler to understand):
var maxes = list.GroupBy(x => x.id2)
.Select(xs => xs.Max(x => x.value));
Or:
var maxes = list.GroupBy(x => x.id2, x => x.value)
.Select(values => values.Max());
Or:
var maxes = list.GroupBy(x => x.id2, // Key selector
x => x.value, // Element selector
(key, values) => values.Max()); // Result selector
Or even:
var maxes = list.GroupBy(x => x.id2)
.Select(xs => xs.Select(x => x.value).Max());
As you can see, GroupBy has lots of overloads :)
Or you could use a query expression:
var maxes = from x in list
group x.value by x.id2 into values
select values.Max();
You shouldn't restrict yourself to either query expressions or the extension method version - it's important to understand both, so you can use whatever's most appropriate.
Apparently OP wants the Value with maximum Id1 within Id2:
Sample data:
public class Row
{
public int Id1;
public int Id2;
public int Value;
}
List<Row> rows = new List<Row>(){
new Row(){Id1=1,Id2=9,Value=12},
new Row(){Id1=2,Id2=9,Value=6},
new Row(){Id1=3,Id2=11,Value=8},
new Row(){Id1=4,Id2=11,Value=87}
};
Solution:
List<int> res = rows.GroupBy(r => r.Id2)
.Select(g => g.OrderByDescending(i=>i.Id1).First().Value)
.ToList();
In case it helps others, I had a similar situation except multiple records needed to be returned instead of a single record.
Eg.
**id1, id2, value**
1 9 12
2 9 6 <-
2 9 7 <-
3 11 8
4 11 87 <-
4 11 88 <-
The following returns the above four records as two lists of two records (enumerable of enumerables):
var maxes = from x in list
group x by x.id2 into xs
select new {values = xs.Where(x => x.id1 == xs.Max(y => y.id1))};
or
var maxes = list.GroupBy(x => x.id2,
(key, xs) => new
{
values = xs.Where(x => x.id1 == xs.Max(y => y.id1))
});
I am using LINQ for the first time and have the following query:
var query = from c in context.Call
join d in context.CallData on c.CallID = d.CallID
where c.CallID == 123
select new {
c.CallID,
c.CallResult,
d.FieldID,
d.FieldValue
};
This returns data similar to the following
c.CallID c.CallResult d.FieldID d.FieldValue
123 Sale 345 John
123 Sale 346 Doe
123 Sale 347 888-222-3333
How can drill down to the row containing d.FieldID = 346 to get the value of d.FieldValue (346 being the LastName field)? I would like to use this value as the new value of a local variable:
// I know this doesn't work, just showing what I would like to accomplish
string LastName = query.Select(a => a.FieldID = 346).FieldValue;
Conversely, how can I change the value of c.CallResult once I have these results? Since it is a join, can I simply change one row of data or do I have to do a separate query?
For the first question you can move on from your query variable:
var fieldValue = query.Where(x => x.FieldID == 346).Single().FieldValue;
As for your second question: you must apply a change to the original entity object:
var call = context.Find(123);
// or context.Calls.Single(c => c.CallId == 123) if this is not DbContext.
call.CallResult = newValue;
context.SaveChanges();
Do you mean:
string LastName = query
.Where(a => a.FieldID = 346)
.Select(a => a.FieldValue)
.FirstOrDefault();
String[] codes = new[] {"C1", "C2" }
Below is the schema for SomeEntity
fkey code
--------------
f1 C1
f1 C2
f2 C2
f2 C3
f2 C4
f3 C5
I have to write queries that can get all the entities based on 2 condition -
1) does the entity have any of the codes
2) does the entity have all the codes
Below is what i wrote for 1st condition
-----------------------------------------
from f in dc.GetTable<SomeEntity>
where codes.Contains(f.code)
select f;
I tried to write 2nd codition by using All operator but "All" operator is not valid for linq to sql.
Question: How to write a query that will return only those entities that have all the codes ?
var codeCount = dc.GetTable<SomeEntity>.Distinct(e => e.Code);
var matching = (from f in dc.GetTable<SomeEntity>
group f by f.Key into grouped
select new { f.Key, values = grouped}).Where(v => v.values.Count() == codeCount);
Probably a hideous query, a stored proc mapped to a function on the data context might be a better solution to be honest
You could probably do the codeCount as let binding in the query and carry on the linq statement rather than close out to the .Where call. Not sure if it'd make it more performant but would save an extra trip to the DB
Try this.
Group by fkey (which will create distinct fkeys)
Filter the groups where
All members of the list of codes are contained within the codes of that group
See below
var matching = dc.GetTable<SomeEntity>()
.GroupBy(e => e.fkey)
.Where(group => codes.All(c =>
group.Select(g => g.code).Contains(code)))
.Select(group => group.Key);
I have the following LINQ conditional where clause query that produces a result of weights:
From this, I'd like to take the result set and join on another table, tblPurchases
var result = weights.Join(getsuppliersproducts.tblPurchases,
w => new { w.MemberId, w.MemberName, w.LocationId, w.UnitId },
p => new { p.MemberId, p.MemberName, p.LocationId, p.UnitId },
(w, p) => p);
In this second table, I have two columns I would like to perform an aggreagte function on, a sum on PurchaseQuantity and a count of UnitID.
So in its raw format, tblPurchases would look like so:
MemberID LocationID UnitId SupplierID SupplierStatus Purchases
1 1 ab Sup1 Live 10
1 1 abc Sup1 Live 10
1 1 abcd Sup2 Dead 50
From my results data set, I would like the output to look like so:
MemberID LocationID SupplierID SupplierStatus UnitIdCount Total Purchases
1 1 Sup1 Live 2 50
Also, with these amendments, can I still return this to a List?
How do I implement this using LINQ? I have tried, and failed miserably.
(To those who have seen my previous posts, I'm trying to cover all angles so I can fully understand the concept of what is going on in both SQL and LINQ)
That query will return an IEnumerable where each of the Purchases matches the MemberId, MemberName, LocationId and UnitId in the original Weights query. You can only easily do one aggregate at a time, so
var result = weights.Join(getsuppliersproducts.tblPurchases,
w => new { w.MemberId, w.MemberName, w.LocationId, w.UnitId },
p => new { p.MemberId, p.MemberName, p.LocationId, p.UnitId },
(w, p) => p).ToList();
Int32 count = result.Count();
Double quantity = result.Sum(p => p.PurchaseQuantity);
Is that what you're trying to do?
EDIT, after your reply of I would like to reutrn a list of tblPurchases with two new columns, the sum of Purchase Quantity and count of unit ID.
This gives a flat output:
var query = Weights.GroupJoin(
Purchases,
w => new {w.MemberId, w.LocationId},
p => new {p.MemberId, p.LocationId},
(w,p) => new {w.MemberId, w.LocationId, Count = p.Count(), Sum = p.Sum(x => x.Purchases)} );
Note that at the point we do the (w, p) => new {} that w is a single Weight and p is a list of Purchases matching that weight, so you can still keep all of teh (hierarchical) data:
var query = Weights.GroupJoin(
Purchases,
w => new {w.MemberId, w.LocationId},
p => new {p.MemberId, p.LocationId},
(w,p) => new {w.MemberId, w.LocationId, Count = p.Count(), Sum = p.Sum(x => x.Purchases), Purchases = p} );
HI there I am hoping for some help with a query I have.
I have this query
var group =
from r in CustomerItem
group r by r.StoreItemID into g
select new { StoreItemID = g.Key,
ItemCount = g.Count(),
ItemAmount = Customer.Sum(cr => cr.ItemAmount),
RedeemedAmount = Customer.Sum(x => x.RedeemedAmount)
};
I am returning my results to a list so I can bind it listbox.
I have a property called EntryType which is an int. There are 2 available numbers 1 or 2
Lets say I had 3 items that my query is working with
2 of them had the EntryType = 1 and the 3rd had EntryType2. The first records had a ItemAmount of 55.00 and the 3rd had a ItemAmount of 50.00
How can I group using something simlar to above but minus the ItemAmount of 50.00 from the grouped amount to return 60.00?
Any help would be great!!
It's not really clear what the question is - are you just trying to ignore all items with an entry type of 2? To put it another way, you only want to keep entries with an entry type of 1? If so, just add a where clause:
var group = from r in CustomerItem
where r.EntryType == 1
group r by r.StoreItemID into g
select new {
StoreItemID = g.Key, ItemCount = g.Count(),
ItemAmount = Customer.Sum(cr => cr.ItemAmount),
RedeemedAmount = Customer.Sum(x => x.RedeemedAmount)
};
Change ItemAmount = ... to:
ItemAmount =
g.Where(x => x.EntryType == 1).Sum(cr => cr.ItemAmount) -
g.Where(x => x.EntryType == 2).Sum(cr => cr.ItemAmount),
I changed Customer to g because this seems to be an error, but it's not clear to me from your question what you mean here, so maybe this change is not what you want.
A slightly more concise method is to use test the entry type in the sum and use the ternary operator to choose whether to add the positive or negative value:
ItemAmount = g.Sum(cr => cr.EntryType == 1 ? cr.ItemAmount : -cr.ItemAmount),
This gives the value of 60.00 as you required.