I have two queries. I want to assign the list values returned from these two queries to a single list, send it to the view and meet it in the view. My goal is to learn to work with lists in C#.
var list1 = c.ETs.Where(p => p.prop != "yes").ToList();
var list2 = c.ETs.Where(p => p.prop == "yes").ToList();
You can merge two lists into one with this:
var newList = List1
.Concat(List2)
.ToList();
Though you could drop the ToList and work directly with the IEnumerable which means you don't need to create a new object.
However, this doesn't even need to be two queries since the Where clauses of both are opposite so they include the entire table, you could do:
var list = c.ETs.ToList();
Or if you want to have two different clauses that aren't simply opposites:
var list = ct.ETs
.Where(p => p.prop == "yes" || p.prop == "no")
.ToList()` for example
This will combine the values of both lists in a single list (the final output will be stored in List1):
List1.AddRange(List2);
Hi Ahmet you can try something like this but note you will need Linq:
var list3 = List1.Concat(List2).ToList();
or if you have more than 2 lists:
var list3 = list1.Concat(list2)
.Concat(list3)
.ToList();
Another method:
var list3 = List1.AddRange(List2);
Both above will create a new list containing both lists' items.
Related
I do a linq to sql query to get a list:
var list1 = db.Table1.Where(a => a.item == "Widgets").ToList();
Now I want to get a list from another table using the results of list above:
var list2 = db.Table2.Where(a => list1.Contains(a.GUID)).ToList();
So far this all works as expected.
Now I want to do a query where I find all rows in another DB table that have GUIDs from my list2
var list3 = db.MyTable.Where(a => list2.Contains(a.GUID)).ToList();
The data types are all the same in the three tables so I know those match. But I get the best overloaded match has some invalid arguments?
You are missing the Where-clause in your third line:
var list3 = db.MyTable.Where(a => list2.Contains(a.GUID)).ToList();
EDIT: Okay, this was only a type and the question was edited, see new answer below.
Looking at your exception
System.Collections.Generic.List.Contains(Test1.Data.Models.Table1)' has some invalid arguments
We can see that list2 is of type List<Test1.Data.Models.Table1>, yet you try to run list2.Contains(long). You have to change
var list2 = db.Table2.Where(a => list1.Contains(a.GUID)).ToList();
to
var list2 = db.Table2.Where(a => list1.Contains(a.GUID)).Select(a => a.GUID).ToList();
Then list2 should be of type List.
I am personally not a big of var because you cannot extract the exact type of a variable from source code. If you change your vars to "real" data types you may see your problem far easier.
I have two lists of 2 different types of classes. I want to select all of the items in the first list that have a property (we'll call it name) that do not have coresponding objects with same name in another list.
For example if I have a list of Age items (joe, 4), (marry,5), (ed,2)
and another list of relation items (joe,father), (ed,brother)
I want to end up with a resulting list of (marry,5)
I was not sure if "except" was somehow used here.
Given two arrays (I'm using anonymous types here, but it's the same deal with proper classes) of different types, you're going to need to extract the excepted 'key' first. In this case the 'key' is the Name property.
//Setup
var ageItems = new [] { new {Name = "Joe", Age=4}, new {Name = "Marry", Age=5}, new {Name="Ed", Age=2} };
var relationItems = new [] { new {Name="Joe", Rel = "Father"}, new {Name="Ed", Rel="Brother"} };
//Get the names
var exceptedNames = ageItems.Select (a => a.Name).Except(relationItems.Select (r => r.Name));
//At this point, we have an `IEnumerable` containing 'Marry', we need to get the instances
var exceptedItems = ageItems.Where(a => exceptedNames.Contains(a.Name));
Of course, being LINQ, you can whack it all into one call:
var exceptedItems = ageItems.Where (a => ageItems.Select (b => b.Name).Except(relationItems.Select (r => r.Name)).Contains(a.Name));
You can't use the .Except overload that takes an IEqualityComparer instance as your classes differ, and IEqualityComparer can only compare two items of the same type, hence we have to generalise and pull out the same fields.
How do I write this linq query:
List<List<string>> listOfLists = new List<List<string>>();
listOfLists.Add(new List<string>(){"Item1", "Item2"});
listOfLists.Add(new List<string>() { "Item2", "Item2" });
//Does listOfLists contain at least one list that has one or more items?
It sounds like you're trying to find if any list has any items. Two ways of doing that:
As described, using Enumerable.Any at both levels (once with a predicate and once without):
var any = listOfLists.Any(list => list.Any());
Just flatten it and see if there are any items at all, as if there is at least one item, it must belong to a list with at least one item:
var any = listOfLists.SelectMany(list => list).Any();
I need to know if the List I am working with contains only some specific values.
var list = new List<string> { "First", "Second", "Third" };
If I want to know if the List contain at least one item with the value "First" I use the Any keyword:
var result = list.Any(l => l == "First");
But how I can write a Linq expression that will return true/false only if the List contains "First" and "Second" values?
I'm not entirely sure what you want, but if you want to ensure that "First" and "Second" are represented once, you can do:
var result = list.Where(l => l == "First" || l =="Second")
.Distinct()
.Count() == 2;
or:
var result = list.Contains("First") && list.Contains("Second");
If you've got a longer "whitelist", you could do:
var result = !whiteList.Except(list).Any();
On the other hand, if you want to ensure that all items in the list are from the white-list and that each item in the white-list is represented at least once, I would do:
var set = new HashSet(list);
set.SymmetricExceptWith(whiteList);
var result = !set.Any();
EDIT: Actually, Jon Skeet's SetEquals is a much better way of expressing the last bit.
Your question is unclear.
From the first sentence, I'd expect this to be what you're after:
var onlyValidValues = !list.Except(validValues).Any();
In other words: after you've stripped out the valid values, the list should be empty.
From the final sentence, I'd expect this:
var validSet = new HashSet<string>(requiredValues);
var allAndOnlyValidValues = validSet.SetEquals(candidateSequence);
Note that this will still be valid if your candidate sequence contains the same values multiple times.
If you could clarify exactly what your success criteria are, it would be easier to answer the question precisely.
You can use Intersect to find matches:
var list = new List<string> { "First", "Second", "Third" };
var comparelist = new List<string> { "First", "Second" };
var test = list.Intersect(comparelist).Distinct().Count() == comparelist.Count();
How can I join 2 lists of equal lengths (to produce a 3rd list of equal length) where I do not want to specify a condition but simply rely on the order of items in the 2 lists.
Eg how can I join:
{1,2,3,4} with {5,6,7,8}
to produce:
{{1,5}, {2,6}, {3,7}, {4,8}}
I have tried the following:
from i in new []{1,2,3,4}
from j in new []{5,6,7,8}
select new { i, j }
but this produces a cross join. When I use join, I always need to specify the "on".
You could use Select in the first list, use the item index and access the element on the second list:
var a = new [] {1,2,3,4};
var b = new [] {5,6,7,8};
var qry = a.Select((i, index) => new {i, j = b[index]});
If you are using .Net 4.0, you can use the Zip extension method and Tuples.
var a = new [] {1,2,3,4};
var b = new [] {5,6,7,8};
var result = a.Zip(b, (an, bn) => Tuple.Create(an, bn));
Alternatively, you can keep them as arrays:
var resultArr = a.Zip(b, (an, bn) => new []{an, bn});
There is a half way solution, if you want to use query syntax. Half way in the sense that you need to use the Select method on both lists in order to get the indexes that you will use in the where clause.
int[] list1 = {1,2,3,4};
int[] list2 = {5,6,7,8};
var result = from item1 in list1.Select((value, index) => new {value, index})
from item2 in list2.Select((value, index) => new {value, index})
where item1.index == item2.index
select new {Value1 = item1.value, Value2 = item2.value};
The benefit with this solution is that it wont fail if the lists have different lengths, as the solution using the indexer would do.