I need to merge 2 list into one list based on a field in the two list and then access the information in the merged list.
Example pseudo code
List1.merge;
List2.merge2;
MergedList = List1.merge join List2.merge2;
MergedList.Merge2 or MergedList.Any Field in List
What about Concat?
var myList = list1
.Where(l => list2
.Any(l2 => l2.Field == l.Field)
.Concat(list2
.Where(l2 => list
.Any(l => l.Field == l2.Field))
.ToList();
how about a simple lambda join?
list1.Join(list2, l1 => l1.Field, l2 => l2.field, (l1,l2) => new SomeORAnonymousObjectType { ListItem1 = l1, ListItemType2 = l2 }).ToArray().ToList().ToEnumerable();
Here is a basic example that you should be able to adjust for you needs:
using System.Linq; // Add these two lines to the using statements
// at the top of your file
using System.Collections.Generic;
var l1 = new List<Uri>() { new Uri("http://www.facebook.com"), new Uri("http://www.yahoo.com"), new Uri("http://www.google.com") };
var l2 = new List<Uri>() { new Uri("http://www.google.com"), new Uri("http://www.nytimes.com"), new Uri("http://www.facebook.com") };
var q = from Uri uri1 in l1
join Uri uri2 in l2 on uri1.Host equals uri2.Host select uri2;
var commonUris = q.ToList(); // Result
The critical line is the one around equals
Be aware that this might not produce the expected result if any item occurs more than once in any one of the lists.
This problem is now solved. I created a list that referenced a class, that stored my information, and once I did this I was able to manage and access everything I needed.
Related
I'm trying to convert a SQL expression to Linq but I can't make it work, does anyone help?
SELECT
COUNT(descricaoFamiliaNovo) as quantidades
FROM VeiculoComSeminovo
group by descricaoFamiliaNovo
I try this:
ViewBag.familiasCount = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo).Count();
I need to know how many times each value repeats, but this way it shows me how many distinct values there are in the column.
You can try:
var list = from a in db.VeiculoComSeminovo
group a by a.descricaoFamiliaNovo into g
select new ViewBag{
familiasCount=g.Count()
};
or
var list = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo)
.Select (g => new ViewBag
{
familiasCount=g.Count()
});
If you need column value:
new ViewBag{
FieldName=g.Key,
familiasCount=g.Count()
};
You don't need the GROUP BY unless there are fields other than the one in COUNT. Try
SELECT
COUNT(descricaoFamiliaNovo) as quantidades
FROM VeiculoComSeminovo
UPDATE, from your comment:
SELECT
COUNT(descricaoFamiliaNovo) as quantidades,
descricaoFamiliaNovo
FROM VeiculoComSeminovo
GROUP BY descricaoFamiliaNovo
That's it as SQL. In LINQ it is something like:
var reponse = db.VeiculoComSeminovo.GroupBy(a => a.descricaoFamiliaNovo)
.Select ( n => new
{Name = n.key,
Count = n.Count()
}
)
Not tested.
Ty all for the help.
I solved the problem using this lines:
// get the objects on db
var list = db.VeiculoComSeminovo.ToList();
// lists to recive data
List<int> totaisFamilia = new List<int>();
List<int> totaisFamiliaComSN = new List<int>();
// loop to cycle through objects and add the values I need to their lists
foreach (var item in ViewBag.familias)
{
totaisFamilia.Add(list.Count(a => a.descricaoFamiliaNovo == item && a.valorSeminovo == null));
totaisFamiliaComSN.Add(list.Count(a => a.descricaoFamiliaNovo == item && a.valorSeminovo != null));
}
The query was a little slow than I expected, but I got the data
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.
I want to attain a list of BeerNames from a list whose names are not on a second list.
var myList=(from f in Beers where ...
select f.BeerNames).ToList
var storeList(from f in Store where...
select f).ToList()
MyList will have some BeerNames that are not on StoreList. How do I find those BeerNames? I tried .Except and !Contains but I realize I'm doing something wrong, and missing some key bit of knowledge.
thanks
If I change
var storeList(from f in Store where...
select f).ToList()
to
var storeList(from f in Store where...
select f.BeerNames).ToList()
then I can use except such as List1.Except(List2). I wasn't sure if there was a better way. Sorry folks if this isn't clear...I'm trying:)
var list1 = new String[] {"ABC1","ABC2", "ABC3", "ABC4"} ;
var list2 = new String[] {"ABC3","ABC4", "ABC5", "ABC6"} ;
var list3 = list1.Except(list2); // list3 holds ABC1, ABC2
Except works fine.
I suspect issue is in the item returned from the linq query.
Seems like f.BeerNames in first, and f in StoreList are not pointing to same datatype.
For heterogenous type
var list1 = from s in new String[] {"ABC1","ABC2", "ABC3", "ABC4"} select new {BeerName=s,Id = Guid.NewGuid().ToString()} ;
var list2 = new String[] {"ABC3","ABC4", "ABC5", "ABC6"} ;
var intermediateList = list1.Select(i=>i.BeerName).Except(list2);
var list3 = from l1 in list1
join l2 in intermediateList on l1.BeerName equals l2
select l1;
list1.Dump(); // run in linqPad
intermediateList.Dump();// run in linqPad
list3.Dump();// run in linqPad
list3 returns following
BeerName Id
ABC1 569ace9a-66c4-46aa-bbf5-50d586a2886f
ABC2 af456094-9692-4771-b489-8b3cca8aa938
Use LinqPad to run the above, or remove .Dump() to execute in VS.
Except should work with the string type
var myList = MyFrig.Select(f => f.BeerNames).Except(Store).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);
I need to retrieve all items from two lists that contains a given value.
Example:
var list1 = {
new Dummy(){ Name = "Dummy1", Number = 1 },
new Dummy(){ Name = "Dummy2", Number = 2 },
new Dummy(){ Name = "Dummy3", Number = 3 }
};
var list2 = {
new Dummy(){ Name = "Dummy4", Number = 4 },
new Dummy(){ Name = "Dummy5", Number = 2 },
new Dummy(){ Name = "Dummy6", Number = 6 }
};
var list3 = GetAllDummiesWithNumbersContainedInBothLists();
I want list3 to contain Dummy2 and Dummy5, since both have the same number.
How do i do this? It should be simple but i cant figure it out...
See if this works for you:
(from dummy1 in list1
join dummy2 in list2 on dummy1.Number equals dummy2.Number
from dummy in new[] { dummy1, dummy2 }
select dummy)
.Distinct()
This pairs matching dummies into the same scope, then flattens out the set so you get all of the matches in one sequence. The Distinct at the end ensures that each dummy appears exactly once even if either list contains repeated numbers.
I'm not entirely sure what your requirements are, but something like this perhaps?
var commonIds = list1.Select(d => d.Number)
.Intersect(list2.Select(d => d.Number));
var commonIdsSet = new HashSet<int>(commonIds);
var list3 = list1.Concat(list2)
.Where(d => commonIdsSet.Contains(d.Number))
.ToList();
if you can clarify the exact requirements (do the results need to be grouped by theNumber, IsNumberunique for an item within a list etc.), we can provide better solutions.
var list3 = list1.Where(d => list2.Select(d2 => d2.Number).Contains(d.Number))
.Union(list2.Where(d2 => list1.Select(d => d.Number).Contains(d2.Number)));
Here's one more!
var list3 = list1
.SelectMany(x => list2
.SelectMany(y =>
(y.Number == x.Number) ? new [] { x, y } : new Dummy[]{}
)
);