Nested lists, how I can do this with lambda expression? - c#

Can't really understand how the select extension method works with a list inside another list, like this:
var queries = (from item in list
from item2 in list.anotherlist
select item2).ToList<MyType>();
This will not work:
// Gives me a list of List<QueryResult>
var queries = list.Select(item => item.anotherlist).ToList();

The SelectMany operator ought to do the trick - in this case, it takes a list of lists and flattens it:
var queries = list.SelectMany(sublist => sublist).ToList();

use selectmany
var queries = list.SelectMany(l => l.anotherList).ToList();

Related

LINQ query to find items in a list containing substring elements from a second list

I am trying to list all elements from the first list where it contains a substring equal to all elements from the second list
First list:
C:\Folder\Files_01026666.pdf
C:\Folder\Files_01027777.pdf
C:\Folder\Files_01028888.pdf
C:\Folder\Files_01029999.pdf
Second list:
01027777
01028888
List result should be:
C:\Folder\Files_01027777.pdf
C:\Folder\Files_01028888.pdf
the closer that I got was with .Intersect() but both string-element should be equals
List<string> resultList = firstList.Select(i => i.ToString()).Intersect(secondList).ToList();
List<string> resultList = firstList.Where(x => x.Contains(secondList.Select(i=>i).ToString()));
List<string> resultList = firstList.Where(x => x == secondList.Select(i=>i).ToString());
I know I can do this another way but I'd like to do it with LINQ.
I have looked at other queries but I can find a close comparison to this with Linq. Any ideas or anywhere you can point me to would be a great help.
We can use EndsWith() with Path.GetFileNameWithoutExtension(), as strings in the secondList are not entire file names.
var result = firstList
.Where(path => secondList.Any(fileName => Path.GetFileNameWithoutExtension(path).EndsWith(fileName)));
Try Online
var q = list1.Where(t=>Regex.IsMatch(t,String.Join("|",list2.ToArray()))));
Seems to work for lists of strings. Using Regex can be problem in LINQ. This won't work in Linq2SQL for example.

How can i split and get distinct words in a list?

My sample data coloumn, which come from an CSV file is
|----Category------------|
SHOES
SHOES~SHOCKS
SHOES~SHOCKS~ULTRA SOCKS
I would love to split the specific column and get the distinct values in a list like
SHOES
SHOCKS
ULTRA SOCKS
I tried the following, but it does not work as expected.
var test = from c in products select c.Category.Split('~').Distinct().ToList();
It actually returns the following.
Any thoughts please? Thank you.
I would use SelectMany to "flatten" the list before removing duplicates:
products.SelectMany(c => c.Category.Split('~'))
.Distinct()
You can use SelectMany to flatten the collection:
products.SelectMany(p => p.Category.Split('~')).Distinct().ToList();
You were close, you just needed to flatten out your collection to pull the individual items of each grouping via a SelectMany() call :
// The SelectMany will map the results of each of your Split() calls
// into a single collection (instead of multiple)
var test = products.SelectMany(p => p.Category.Split('~'))
.Distinct()
.ToList();
You can see a complete working example demonstrated here and seen below :
// Example input
var input = new string[] { "SHOES","SHOES~SHOCKS","SHOES~SHOCKS~ULTRA SOCKS" };
// Get your results (yields ["SHOES","SHOCKS","ULTRA SOCKS"])
var output = input.SelectMany(p => p.Split('~'))
.Distinct()
.ToList();
Merge this list of list of strings into a single list by using SelectMany() and Just add another Distinct to your List..
var test = from c in products select c.Category.Split('~').Distinct().ToList().SelectMany(x => x).Distinct().ToList();
Here's how you'd do it in query syntax.
var test = (from p in products
from item in p.Category.Split('~')
select item).Distinct().ToList();

Add new record to linq query result

I have a query as follows:
var paymentInfo =
from i in dbconnect.tblPayments
where i.tenderId == _tenderId
select i;
This query has some results, but I need to add an additional result that I already have, from the variable PaymentInfo.
For example suppose that my query has 2 results i need to add another result to "PaymentInfo" using linq.
I thought that the result is a kind of list, and that I could call .Add(PaymentInfo), but this doesn't work
How can I do this?
You can use Concat to concat another sequence to the end of this one.
var paymentInfo = paymentInfo.Concat(someOtherPayments);
I thought that the result is a kind of list
No, the result is an IEnumerable<T> which is read-only. You can create a list by calling .ToList() and then add an item to it.
var paymentInfo = (from i in dbconnect.tblPayments
where i.tenderId == _tenderId
select i).ToList();
paymentInfo.Add(existingPayment);

Flatten a C# Dictionary of Lists with Linq

I have a Dictionary in C#:
Dictionary<string, List<string>>
How can I use Linq to flatten this into one List<string> that contains all of the lists in the Dictionary?
Thanks!
Very easily:
var list = dictionary.Values // To get just the List<string>s
.SelectMany(x => x) // Flatten
.ToList(); // Listify
Here the SelectMany call takes a sequence of inputs (the lists which make the values of the dictionary) and projects each single input into another sequence of outputs - in this case "the elements of the list". It then flattens that sequence of sequences into a single sequence.
as a query
var flattened = from p in dictionary
from s in p.Value
select s;
or as methods...
var flattened = dictionary.SelectMany(p => p.Value);
I like this over what others have done as I'm passing the whole dictionary into the Linq query rather than just the values.
SelectMany is the easiest way to flatten things:
Dictionary.Values.SelectMany(x => x).ToList()
Assuming you have an instance called dict:
dict.SelectMany(pair => pair.Value.Select(str => str));
You should try something like this:
dict.Values.Aggregate(new List<String>(), (a, b) => a.Concat(b));

linq - selecting elements not equal to something

Suppose I have a collection of strings.
How do I select all the elements that don't contain a certain parameter value?
List<string> TheList = .....
var TheCleanList = (from s in TheList
where s != parameter
select s).ToList();
I was thinking about where s!= parameter but I'm wondering if there's a cleaner way to do it.
Thanks.
If you don't need a new list you don't need Linq for this - use Remove()- this avoids having to create a new list:
If you want to remove all strings that are equal to Parameter:
TheList.RemoveAll(s => s == Parameter);
If you want to remove all strings that contain Parameter (not clear from your question):
TheList.RemoveAll(s => s.Contains(Parameter));
You mean:
List<string> TheList = .....
var TheCleanList = (from s in TheList
where !s.Contains(parameter)
select s).ToList();
You can use String.Contains
var TheCleanList = (from s in TheList
where !s.Contains(parameter)
select s).ToList();
Or
var TheCleanList = TheList.Where(s => !s.Contains(parameter)).ToList();
String.Contains is case-sensitive. If you want a case-insensitve:
string lower = parameter.ToLower();
...
where s.ToLower().Contains(lower)

Categories