I have this query so far:
var msg = ModelState.Values
.Where(x => x.Errors.Any())
.Select(c => c.Errors.Select(d => d.ErrorMessage).Aggregate((e, f) => (e ?? "") + "<br/>" + f))
.Aggregate((x, y) => (x ?? "") + "<br/>" + y);
This is working perfectly, but I need to filter out the duplicate error messages. I have tried adding both GroupBy() and Distinct() to several places both prior to and following the predicate that obtains the ErrorMessage. What am I missing?
If I run this as it is, I receive the following result:
"Contact Email address invalid<br/>Contact Email address invalid"
Each ErrorMessage value here is "Contact Email address invalid". These are the duplicates that I would like to filter out.
Can I suggest an alternative?
Assuming you want distinct messages, separated by the break tag:
var items = ModelState.Values
.SelectMany(c => c.Errors.Select(d => d.ErrorMessage))
.Distinct()
.ToArray();
string msg = string.Join("<br/>", items);
The problem is that you've got two places producing values. Consider the following case:
Value Errors
1. "Bad username", "Contact Email address invalid"
2. "Contact Email address invalid"
Even if you add Distinct to both Select calls, it won't do what you want, as Bad username<br/>Contact Email address invalid will be compared to Contact Email address invalid, will be found not to be equal, and will be aggregated into Bad username<br/>Contact Email address invalid<br/>Contact Email address invalid, which, I assume, is not what you want.
Instead, you should be flattening the nested lists of errors first. This is the job of SelectMany. To flatten your list, you just need to do:
var errorMessages = ModelState.Values
.Where(x => x.Errors.Any())
.SelectMany(c => c.Errors.Select(d => d.ErrorMessage))
Now errorMessages is a list of every error message from every Value. (Note that the Where is probably unneeded: Select or SelectMany on an empty sequence is a no-op.)
Now there is the second issue:
It is almost always bad practice to use + with strings in C#, due to string's immutablity. Instead, you want to use string.Join, string.Format, or StringBuilder depending on if your input is a sequence, multiple variables or longer strings. In this case you have an array, so string.Join is the tool of choice:
var msg = string.Join("<br/>", errorMessages.Distinct())
Related
How to find string with a exact match in the list of string.
var inv_attr_string_id = inv_attr
.Where(x => ItemStringVal.Contains(x.STRING_VAL))
.Select(x => x.ID).ToList();
ItemStringVal Contains list of Strings like "0030", "1433", "2019" etc ... Now I am trying to match it with the database in such a way that if it match exactly and all the three strings then it returns me the list of IDs matched ... else it should return null.
I tried
List<int> inv_attr_string_id = new List<int>();
foreach (var StrItem in ItemStringVal)
{
inv_attr_string_id.AddRange
(
inv_attr.Where(x => x.STRING_VAL.Contains(StrItem))
.Select(x => x.ID).ToList()
);
}
I have tried .Any as well but I got an error saying "Internal .NET Framework Data Provider error 1025"
I was thinking if I could be able to write it the way it creates a query of AND condition such as it should match (Exactly) all the input strings.
One Liner could be: Select IDs if all the string matches. Else return null
If I understand the problem - You have a list of strings which is your Input Data. You also have a List of patterns that may match with Data. You want to find the pairs of [Data, Pattern]?
Upfront this can be solved in O(N^2).
Psuedo Logic be like:
Foreach item in DataCollection
Foreach pattern in PatternCollection
if(Regex.IsMatch(item, pattern)) Then collect the item & pattern in some place
Hope this gives some starting point for you to solve the problem.
You can try linq to get all those records from db which are exist int your list
var result = inv_attr.AsEnumerable().Where(x => ItemStringVal.Exists(y => y == x.STRING_VAL)).Select(x => x.Id).ToList();
In a part of my code, I'm converting an IEnumerable list to a string.
String.Join(", ", e.User.Roles.Select(o => o.ToString()))
resolves to for example:
Admin, #everyone
This is using Discord.Net SDK where Roles is an IEnumerable containing all the 'ranks' of the user.
There's a default role that every user is apart of which I want to remove from the string. The default role can be called by using
e.Server.EveryoneRole
My idea was to use Except to filter the default role which resulted to
System.Linq.Enumerable+<ExceptIterator>d__72`1[System.Char], System.Linq.Enumerable+<ExceptIterator>d__72`1[System.Char]
or just simply filtering out #everyone is also good in my case.
Can't you just use a where, such as the following?
String.Join(", ", e.User.Roles
.Where(o => o != e.Server.EveveryoneRole)
.Select(o => o.ToString()))
Use a line Where clause.
Something like:
String.Join(", ", e.User.Roles.Select(o => o.ToString()).Where(s => s != e.Server.EveveryoneRole)
Cannot find the lambda linq equivalent to SELECT * FROM [Source] WHERE [Field] IN [String Array]. I need to select all data from a data table that contains zip codes from a string array. I would like a faster way than just iterating through every row comparing them as I believe this would be fairly inefficient (or I believe it would anyway). I can't seem to find an adequate answer on Google of how to perform a lambda LINQ IN query on a data table. Any assistance would be great! Here is what I have currently:
List<string> lst = dtEtechZipCodeEmailRecipients.AsEnumerable()
.Select(o => o.Field<string>("Email")).Distinct().ToList();
for (int i = 0; i < lst.Count - 1; ++i)
{
string email = lst[i].ToString().ToUpper();
string[] zipCodes = dtEtechZipCodeEmailRecipients.AsEnumerable()
.Where(zip => (zip.Field<string>("Email") ?? (object)String.Empty).ToString().ToUpper() == email)
.Select(zip => zip.Field<string>("ZipCode")).ToArray();
Console.WriteLine(" - " + email);
dtEtechModelRequests.AsEnumerable().Where(mod => mod.Field<string>("ZipCode").Contains(zipCodes)).Select(mod => mod);
}
That does not work, everything but the .Contains does do exactly what I need though. I left the .Contains to try and demonstrate my point.
You should do opposite thing - check whether array of zip codes contains current zip code:
Where(mod => zipCodes.Contains(mod.Field<string>("ZipCode"))
That is same as verifying if current zip code IN array.
Simple answer to your question is,
[Source].Where(el => [String Array].Contains(el.Field<string>("Field"))
And if you need NOT IN then follow the following pattern
Adding ! infront of your [String Array]
[Source].Where(el => ![String Array].Contains(el.Field<string>("Field"))
alternative representation
[Source].Where(el => [String Array].Contains(el.Field<string>("Field")==false)
if (DataList.Any(item => item.ID == int.Parse(Txtbox2.Text)))
{
Txtbox1.Text += string.Join(";", DataList.Select(o => o.DataString()));
}
I am trying to get the list into a textblock but only the items that meet a certain criteria.
The only thing I have is it displaying the whole list when the IF is met, is the any way for me to put a condition in the part that actually makes the list?
EDIT: all the DataString method is, is a method in the Data Class that converts all the vairous data types into a string output.
You want to use Where, rather than Any:
int value = int.Parse(Txtbox2.Text); //consider using TryParse here
var strings = DataList.Where(item => item.ID == value)
.Select(item => item.DataString());
Txtbox1.Text += string.Join(";", strings);
Also note that rather than parsing the textbox value over and over again, it's worth parsing it once and storing the result in a variable.
The following will select the name of a user who votes positively on an item and then put it in a comma separated string.
var string = string.Join(", ", comment.CommentVote.Where(v=> v.Vote == true).Select(v => v.User.FirstName).ToArray());
I want to be able to get the first and last name, put them together, and then list them out in a comma separated list.
Context: I am trying to create something similar to Facebook:
John Doe and 25 others like this
Where "25 others" provides a list of users on hover. I can loop through the users who voted and get the first and last names, concatenate them, and then add a comma, it just seems like there should be something simpler that lets me avoid the foreach loop.
Just concatenate them:
var str = string.Join(", ",
comment.CommentVote
.Where(v=> v.Vote)
.Select(v => v.User.LastName + " " + v.User.FirstName));
Besides you don't need to call ToArray() explicitly, as string.Join has an overload accepting IEnumerable<T>. And you cannot have a variable with the name string, as it's an alias for type System.String.
You can just join the to value you want in the select statement.
var results = string.Join(", ", comment.CommentVote.Where(v=> v.Vote)
.Select(v => string.Format("{0} {1}", v.User.FirstName, v.User.LastName)));
EDIT: Opps sorry, Konstantin Vasilcov already answered