I used linq to create a list of IO_EQUATIONS. An IO_EQUATION consists of a single OUTPUT_POINT and a List of INPUT_POINT. INPUT_POINT and OUTPUT_POINT have a common x, y, and z coordinate but they contain other fields that are not common. I want to flatten out the List of IO_EQUATIONS to either an anonymous type or a specific point type (x, y, and z only) so that I see the Output followed by all the inputs for each IO_EQUATION in a list.
I was able to use linq to list all the OUTPUT_POINTS using the following code. list41 is the list of IO_EQUATIONS
var flat = (from d2 in list41
select (new BINARY_IO()
{
propX = d2.propOutputPoint.propX,
propY = d2.propOutputPoint.propY,
propZ = d2.propOutputPoint.propZ,
propDir = POINT_DIRECTION_Types.Output,
})).ToList();
I was able to use linq to list all the INPUT_POINTS using the following code.
list41 is the list of IO_EQUATIONS. propIOPointList is my list of INPUT_POINT
var flat = (from d2 in list41
from d3 in d2.propIOPointList
select (new BINARY_IO()
{
propX = d3.propX,
propY = d3.propY,
propZ = d3.propZ,
propDir = POINT_DIRECTION_Types.Input,
})).ToList();
I can get the information separately by I want the data to be formatted as an output followed by the inputs, then the next output followed by the inputs, etc.
I have a feeling this is really simple and I just can't get it to work.
Thanks
To flatten a list of list in LINQ, use .SelectMany
var flattenedList = list1.SelectMany(i => i.PropertyThatIsAList)
Many similar questions, for example :
Flatten List in LINQ
The easiest way is to transform each item in list41 into an IEnumerable<BINARY_IO> in the order you listed, then using SelectMany to flatten the resulting IEnumerable<IEnumerable<BINARY_IO>>.
var flat =
(from d2 in list41
select
Enumerable.Repeat(
new BINARY_IO {
propX = d2.propOutputPoint.propX,
propY = d2.propOutputPoint.propY,
propZ = d2.propOutputPoint.propZ,
propDir = POINT_DIRECTION_Types.Output}, 1)
.Concat(
from d3 in d2.propIOPointList
select new BINARY_IO {
propX = d3.propX,
propY = d3.propY,
propZ = d3.propZ,
propDir = POINT_DIRECTION_Types.Input}))
.SelectMany(i => i)
.ToList();
Note that I use Enumerable.Repeat(v, 1) to get a singleton, there are other methods as well.
Additionally you could inline the call to SelectMany but at that point you might want to switch away from query syntax and just use a manual call to Select for the second from/select.
Related
I have 2 lists of Objects. I am using Intersect LINQ operator to any match between 2 lists and setting it as a variable. In this newly formed list, I am only able to get the matched value.
I've looked into SelectMany, but don't think it's the right solution for this.
var CommonList = iMIScustomersList.Select(s1 => s1.Company).ToList().Intersect(zendeskCompaniesList.Select(s2 => s2.name).ToList()).ToList();
I want to get the matched value and from the matched value in list 2, I want to get the id property as well. For example s2.id in zendeskCompaniesList. Currently using Intersect I am only getting the matched value and no other properties from that match.
What you need is Join, instead of Intersect.
var CommonList = iMIScustomersList.Join(zendeskCompaniesList,
cust=>cust.Company,
comp=>comp.Name,
(cust,comp)=> new {Customer=cust,Company=comp}).ToList();
For example,
var iMIScustomersList = Enumerable.Range(1,10)
.Select(x=> new Customer{Name = $"Name{x}", Company=$"Company{x}"});
var zendeskCompaniesList = Enumerable.Range(5,10)
.Select(x=> new Company{Name=$"Company{x}", Location = $"Location{x}"});
var CommonList = iMIScustomersList.Join(zendeskCompaniesList,
cust=>cust.Company,
comp=>comp.Name,
(cust,comp)=> new {Customer=cust,Company=comp}).ToList();
Sample Output
Recently I have a task which need to do as following description, my question is that is LINQ capable to do it?
Say I have a set of data, each consists of three columns: a(int),b(int),c(int)
What I want to do is to group these data by a and b, and for each distinct pair (a,b), store their corresponding c into separate list.
For example: If I have a set of data(a,b,c) {(1,3,5), (2,4,6), (1,3,7), (2,4,8)},
I want to split the data into two separate list, each contains c's value:
List 1 (a=1,b=3) : [5,7]
List 2 (a=2,b=4) : [6,8]
What I have tried is to group / order by the data by (a,b), and got a sorted list of data, I can of course use any loop to iterate the set of data and split them into several list, just wondering if there is a more beautiful solution, like using a single LINQ query?
Any suggetion is pleased! Thanks :)
Try this:
var result = data.GroupBy(x => new { x.a, x.b })
.Select(g => Tuple.Create
(
new List<int> { g.Key.a, g.Key.b },
new List<int>(g.Select(x => x.c))
)).ToList();
Here's the query expression equivalent:
var result = (from x in data
group x by new { x.a, x.b } into g
select Tuple.Create(
new List<int> { g.Key.a, g.Key.b },
new List<int>(g.Select(x => x.c)))).ToList();
I try Get 5 Object in each group to display.
I tried code like this:
var BBS = (from bb in db.Object
where SubjectList.Contain(bb.Type)
select new ObjectModel {
Subject = bb.Subject,
CDate = bb.CDate
}).GroupBy(a => a.BBSTypeSubject).Take(5);
but it doesn't work.
and then I try it by using Foreach
First off, realize that C# is case sensitive, so you need to spell function names like Take and Contains correctly. But you can solve this problem fairly easily by just using this overload of GroupBy instead.
var BBS = (from bb in db.Object
where SubjectList.Contains(bb.Type)
select new ObjectModel {
Subject = bb.Subject,
CDate = bb.CDate
}).GroupBy(a => a.BBSTypeSubject, (k, g) => g.Take(5));
The second parameter allows you to specify what result object will be returned for each group. In this case, I simply take the first 5 items from the group and return those instead.
When you select new ObjectModel, there's no property called BBSTypeSubject. You need to include that. So it should be
select new ObjectModel {
Subject = bb.Subject,
CDate = bb.CDate,
BBSTypeSubject= ???
}
I asked this question earlier and that helped a lot. Then I realized I also need a list of IDs of the List that is a property in that object. Basically I want to end up with a list of integers generated from each list in those objects. Any ideas?
Thanks!
var ids = (from x in outerList
from y in x.List
select y).ToList();
Or to avoid dups:
var ids = (from x in outerList
from y in x.List
select y).Distinct().ToList();
For info, this could also be written:
var ids = outerList.SelectMany(x => x.List).ToList();
or:
var ids = outerList.SelectMany(x => x.List).Distinct().ToList();
I need to retrieve a list of entities from my database that matches a list of items in a plain list (not EF). Is this possible with Entity Framework 4.1?
Example:
var list = new List<string> { "abc", "def", "ghi" };
var items = from i in context.Items
where list.Contains(i.Name)
select i;
This works great to return rows that match one property, but I actually have a more complex property:
var list = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
// i need to write a query something like this:
var items = from i in context.Items
where list.Contains(new Tuple<string,string>(i.Name, i.Type))
select i;
I know that is not valid because it will say it needs to be a primitive type, but is there any way to do what I'm trying to accomplish or will I need to resort to a stored procedure?
You have a few options:
1) You could, of course, write a stored procedure to do what you need and call it.
2) You could read the table into memory and then query the in memory list...that way you don't have to use primitives:
var items = from i in context.Items.ToList()
where list.Contains(new Tuple<string, string>(i.Name, i.Type))
select i;
3) You could also convert your query to use primitives to achieve the same goal:
var items = from i in context.Items
join l in list
on new { i.Name, i.Type } equals
new { Name = l.Item1, Type = l.Item2 }
select i;
I would go with the second option as long as the table isn't extremely large. Otherwise, go with the first.
You need to break it down to sub-properties. For example, something like (this might not compile, i'm not able to test at the moment, but it should give you something to work with):
var items = from i in context.Items
where list.Select(x => x.Item1).Contains(i.Name)
&& list.Select(x => x.Item2).Contains(i.Type)
select i;
You have to think about what the resulting SQL would look like, this would be difficult to do directly in SQL.
My suggestion would be you split out one field of the tuples and use this to cut down the results list, get back the query result then filter again to match one of the tuples e.g.
var list = new List<string> { "abc", "def" };
var list2 = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
var items = (from i in context.Items
where list.Contains(i.Name)
select i)
.AsEnumerable()
.Where(i => list2.Any(j => j.val1 == i.Name && j.val2 == i.Type);