linq - selecting elements not equal to something - c#

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)

Related

Convert linq query to Generic string array

I know that I can cast my linq query to an array or list but this doesn't seem to help.
Here is my query:
var bracct = from DataRow x in _checkMasterFileNew.Rows
select new {BranchAccount = string.Format("{0}{1}", x["Branch"], x["AccountNumber"])};
When I attempt to convert it to a list or array:
List<string> tstx = bracct.ToList();
or this:
string[] stx = bracct.ToArray();
If give me this:
I am assuming I need to change my query but I'm not sure the best way to hanlde it. How do I get it to a generic collection of strings?
It won't work because you've created an anonymous type with 1 property which is a string. Instead, If all you want is to convert it into a List<string> do:
var bracct = (from DataRow x in _checkMasterFileNew.Rows
select string.Format("{0}{1}", x["Branch"], x["AccountNumber"])).ToList();
And if using c# 6.0 you can use string interpolation:
var bracct = (from DataRow x in _checkMasterFileNew.Rows
select $"{x["Branch"]}{x["AccountNumber"]}").ToList();
Your query is creating an anonymous type with a single member BranchAccount. If you actually just want a string, then just select that instead:
var bracct =
from DataRow x in _checkMasterFileNew.Rows
select string.Format("{0}{1}", x["Branch"], x["AccountNumber"]);
And now your ToList() call will return List<string>:
List<string> tstx = bracct.ToList();
You must select the property you are assigning the string to before performing ToList(), or remove the anonymous type and select string.Format() directly
Try this:
List<string> tstx = bracct.Select( x => x.BranchAccount ).ToList();

Object.CategoryName into List<string> of category names

I have List<MyObject> listObjects where I would like a unique list of MyObject.CategoryName as List<string>.
I have the following linq so far.
var categoryNames = from element in listObjects
orderby element.CategoryName
group element by element.CategoryName;
However, var categoryNames is a IEnumerable<IGrouping<string, MyObject>>.
How can I get the list as a List<string>?
thank you.
var categoryNames = listObjects.Select(x => x.CategoryName).Distinct().ToList();
In words: "Grab only the category names, and then ignore duplicates, and put them into a list."
var categoryNames = listObjects.Select(o=>o.CategoryName).Distinct().ToList()

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

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

FindAll search question

I have a list like this:
item.Add("a");
item.Add("as");
item.Add("b");
item.Add("fgs");
item.Add("adsd");
How can I find all items that start with (for example) "a"?
This "a" is not some hardcoded string, so I will need a function that do this for each string.
I try with FindAll, but I did not figured out how it works.
Br, Wolfy
If by "start with" you mean the first char, then:
item.FindAll(i => i[0] == 'a');
if you mean a string (may be other than 1 char) then:
item.FindAll(i => i.StartsWith("a"));
If you want a different comparison, such as case-insensitive, locale-based, etc. then do the relevant IndexOf such as:
item.FindAll(i => i.IndexOf("a", StringComparison.CurrentCultureIgnoreCase) == 0);
All of the above can be easily adapted to be use a relevant char or string variable or parameter.
If you don't need the extra properties and methods provided by a list, then it will be more efficient to use Where than FindAll as FindAll creates a new list, and does so in all at once, while Where will enumerate the matching results as it is iterated through.
Or with LINQ
from i in items where i.StartsWith("a") select i;
for NET2.0 you may use this method:
'pattern' is an argument to look for (f.e. "a")
private List<string> FindAll(List<string> list, string pattern)
{ // returns found results
return list.FindAll(delegate(string item)
{
return item.StartsWith(pattern);
});
}
I thought you have another list that contains the startswith criteria strings. Lets call your items "words" and the other list "keywords". So the below query will return what you want.
List<string> words = new List<string>();
words.Add("a");
words.Add("as");
words.Add("b");
words.Add("fgs");
words.Add("adsd");
List<string> keywords = new List<string>();
keywords.Add("a");
keywords.Add("b");
var result = words.FindAll(o =>
keywords.Any(a => o.StartsWith(a))
);
This result has the words that starts with any of the keyword from keywords.
List<string> item = new List<string>();
item.Add("a");
item.Add("as");
item.Add("b");
item.Add("fgs");
item.Add("adsd");
var res1 = item.FindAll(i => i.StartsWith("a"));
var res2 = item.Where(i => i.StartsWith("a"));
Try this
item.FindAll(i => i.Contains("a"));
This will return a List containting only the filtered strings.

return string[] from LINQ IQueryable object?

I'm trying to work with the .NET AJAX autocompletion extension. The extension is expecting the following...
public static string[] GetCompletionList(string prefixText, int count, string contextKey)
My database queries are in a LINQ var object. I'm getting compile-time errors about not being able to convert type IQueryable to string[].
InventoryDataContext assets = new InventoryDataContext();
var assetsInStorage = from a in assets.Assets
where a.Name.Contains(prefixText)
orderby a.Name ascending
select new[] { a.Manufacturer.Name, a.Name };
return (string[])assetsInStorage;
In order to get an string[] at first you must select only one string property on your query, not an anonymous object:
var assetsInStorage = from a in assets.Assets
where a.Name.Contains(prefixText)
orderby a.Name ascending
select a.Manufacturer.Name; // or a.Name
assetsInStorage at this moment is an IEnumerable<string>, and then you should convert it to string[] by:
return assetsInStorage.ToArray();
Your assetsInStorage doesn't appear to be an IEnumerable<string>... as such, you'd have to project your anonymous type into a string.
assetsInStorage.Select(a=>a[0] + a[1])
(Or however you want to convert that anonymouns type to a string.)
And then you can return .ToArray():
return assetsInStorage.Select(a=>a[0]+a[1]).ToArray();
If you want a single array that contains both a.Manufacturer.Name and a.Name for each of the assets, you can do that with a slight modification of CMS's answer:
var assetsInStorage = from a in assets.Assets
where a.Name.Contains(prefixText)
orderby a.Name ascending
select new[] { a.Manufacturer.Name, a.Name };
At this point, assetsInStorage is an IEnumerable<string[]> which also counts as an IEnumerable<IEnumerable<string>>. We can flatten this down to a single IEnumerable<string> using SelectMany and then turn it into an array.
return assetsInStorage.SelectMany(a => a).ToArray();
In this way, you're not required to select only a single string value.
This should do the trick:
InventoryDataContext assets = new InventoryDataContext();
var assetsInStorage = from a in assets.Assets
where a.Name.Contains(prefixText)
orderby a.Name ascending
select String.Concat(x.ManufacturerName, " ", x.Name);
return assetsInStorage.ToArray();
EDITED based on comment... EF is able to interpret String.Concat(), so the additional enumeration wasn't necessary.
Try:
return assetsInStorage.ToArray();

Categories