Linq: Produce one result from two linq sources - linq

I have two linq statements which both prouce an output of the same tye. How do can I merge this two linqstatements into, so that I get a single list.
Example:
var list1 = new List<string>() {"hello", "world", "!"};
var list2 = new List<string>() {"hello 2", "world 2", "! 2"};
var linq1 = from item in list1
where item.Contains('o')
select item;
var linq2 = from item in list2
where item.Contains('l')
select item;
var joined = linq1.Concat(linq2);
Output:
[0]: "hello"
[1]: "world"
[2]: "hello 2"
[3]: "world 2"
I want to have this in a single linq statement.

You just use Concat as you have. But instead of linq.Concat(linq2), you just put the queries there:
var joined = list1.Where (w => w.Contains("o"))
.Concat(list2.Where (w => w.Contains("l")));
Concat doesnt have a query syntax equivalent. (http://msdn.microsoft.com/en-us/library/bb386979(v=vs.110).aspx)
So you'd do something like this:
var joined = (from item in list1
where item.Contains('o')
select item)
.Concat(from item in list2
where item.Contains('l')
select item);

Related

looping through 2 lists to get the results

I have two lists:
myObject object1 = new myObject(id = 1, title = "object1"};
myObject object2 = new myObject(id = 2, title = "object2"};
myObject object3 = new myObject(id = 3, title = "object3"};
//List 1
List<myObject> myObjectList = new List<myObject>{object1, object2, object3};
//List 2
List<int> idList = new List<int>{2, 3,5};
Now I need to get output as follows:
If a id is present in both the lists, I need to print "A",
if a id is present in list1 only, then I need to print "B",
...and if the id is present in list2 only, I need to print "C"
Can I use linq to achieve this?
I would simply use the inbuilt functions of Except and Intersect
List1.Intersect(List2) = "A"
List1.Except(List2) = "B"
List2.Except(List1) = "C"
There are plenty of resources online about how you could go about doing this, as one example (I didn't look into it too much), check out this link - Linq - Except one list with items in another
Hope this does the trick...

linq list string like

I have a list:
List(Of String)
I want to filter it with LINQ.
I use things like this:
newList = (From l In myList Where l Like String.Format("%{0}%", value)).ToList
Value is something like a or no, etc.
I want something like a LIKE in SQL:
like "%a%"
So I that will result a list of string where there is a a in each string.
How should I do that?
dim list1 as list(of string)
list1.Add("aaa")
list1.Add("bbb")
list1.Add("ccc")
list1.Add("abc")
list1 = from l in list1 where ???? 'like "a" return list1 with 2 item : "aaa" and "abc"
List a = new List();
a = a.Where(item => item.contains("a")).ToList();
In C#:
var newList = originalList.Where(item => item.Contains("a")).ToList();
In VB.Net:
dim newList = originalList.Where(Function(item) item.Contains("a")).ToList
(From I in Mylist
Where I.smth Contains(String)
Select I);
For a list of String you can do that :
(From I in Mylist
Where I.smth Contains(String(0)) Or I.smth Contains(String(1))...
Select I);
If you don't know how much strings you'll get, you might also need dynamic queries. It's quite more difficult and I won't be able to explain it

linq join 1 to many get first record

I have 2 list:
List1:
ID
1
2
3
List2:
ID Name
1 Jason
1 Jim
2 Mike
3 Phil
I like to join both of these but get only the first record from list2 for a given ID:
The end result would be
ID Name
1 Jason
2 Mike
3 Phil
I tried the following but was not successful:
var lst = (from lst1 in list1
join lst2 in list2
on lst1.ID equals lst2.ID).ToList().First();
You can get this result with what the 101 LINQ Samples calls "Cross Join with Group Join". Combine that with First() to get just one item from the group.
var lst = (
from lst1 in list1
join lst2 in list2 on lst1.ID equals lst2.ID into lstGroup
select lstGroup.First()
);
Example: http://ideone.com/V0sRO
Try grouping list2 by ID first and then selecting the first item from each group. After that, do the join and select what you want.
var uniqueIDList2 = list2.GroupBy(p => p.ID)
.Select(p => p.First());
var result = from lst1 in list1
join lst2 in uniqueIDList2 on lst1.ID equals lst2.ID
select new { lst1.ID, lst2.Name };
Here's one way to do it:
var lst = list1
// Select distinct IDs that are in both lists:
.Where(lst1 => list2
.Select(lst2 => lst2.ID)
.Contains(lst1.ID))
.Distinct()
// Select items in list 2 matching the IDs above:
.Select(lst1 => list2
.Where(lst2 => lst2.ID == lst1.ID)
.First());
Example: http://ideone.com/6egSc
Another way:
var query = from lst1 in list1
let first = list2.FirstOrDefault(f => f.Id == lst1.Id)
where first != null
select first;
Or if you wanted to know about items that could not be located in list2:
var query = from lst1 in list1
let first = list2.FirstOrDefault(f => f.Id == lst1.Id)
select first ?? new { Id = 0, Name = "Not Found" };

Linq List contains specific values

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();

Join 2 lists by order instead of condition in LINQ

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.

Resources