I have the following code
var returnData = DemoData.Books.AsQueryable();
if (criteria.Author != string.Empty)
{
returnData = returnData.Where(x => x.Author.Contains(criteria.Author));
}
How do I made the where clause case insensitive?
You can use ToLower() function. ToLower changes strings to be all lowercase. It converts an entire string—without changing letters that are already lowercased or digits. It copies a string and returns a reference to the new string. So it is always better option to declare criteria.Author.ToLower() outside the query.
string lowerAuthor = criteria.Author.ToLower();
returnData = returnData.Where
(x => x.Author.ToLower().Contains(lowerAuthor));
You could also use IndexOfoverload with the StringComparison enum. It would give you better performance than ToLower(). The signature of this overload is:
int string.IndexOf(string value, StringComparison comparisonType);
returnData = returnData.Where
(x => x.Author.IndexOf(criteria.Author, StringComparison.CurrentCultureIgnoreCase) != -1);
returnData = returnData.Where
(x => x.Author.IndexOf(criteria.Author, StringComparison.CurrentCultureIgnoreCase) != -1)
It will make no additional string allocation at all.
I assumed it's LINQ to Objects query.
Related
Suppose I have this array of char:
private char[] _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
.ToCharArray();
I want find the index of the character B, so the code must return 1.
I wrote this method:
public int? GetCharIndex(string code)
{
return _alpha.FirstOrDefault(c => c.ToString() == code.ToUpper());
}
where code is b. The result of GetCharIndex is: 66, why I get this result?
Thanks in advance for any help.
use Array.IndexOf
https://learn.microsoft.com/en-us/dotnet/api/system.array.indexof?view=netframework-4.7.2
The 66 you are getting is 'B' ascii value.
The FirstOrDefault function returns the actual item (B) not the index.
So:
int index = Array.IndexOf(_alpha, code.ToUpper());
As you've mentioned, you'd like to use Linq. The Select in LINQ has an override that let's you expose the index. Getting the first matching value will give us the index of the occurrence. You can also replace the .FirstOrDefault() to .ToList() if you want all indexes on the match.
ToList
char[] _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToArray();
var code = "b";
var key = _alpha.Select((s, i) => new { i, s })
.Where(t => t.s.ToString().ToUpper() == code.ToUpper())
.Select(t => t.i)
.ToList();
Alternatively the above can also be written as
FirstOrDefault
return _alpha.Select((s, i) => new { i, s }).FirstOrDefault(t => t.s.ToString().ToUpper() == code.ToUpper()).i;
Why I get this result?
Nullable<Char> is implicitly convertible to Nullable<Int32> because Char is implicitly convertible to Int32. That happens in your return statement. You're returning the character from the array if found.
Where people are saying ASCII code, they mean character code; in particular, since .NET uses the UTF-16 character encoding of the Unicode character set the UTF-16 code unit value.
BTW—VB4/5/6/A/Script, Java, JavaScript, … also use UTF-16 for text datatypes.
To use standard LINQ operators, choose one that supplies an index like Select:
Char[] _alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
Func<Char, StringComparison, Int32?> GetIndexOf = (code, comparisonType) => {
var value = code.ToString();
return _alpha
.Select((c, i) => c.ToString()
.Equals(value, StringComparison.InvariantCultureIgnoreCase) ? i : (Int32?)null)
.FirstOrDefault(i => i.HasValue); } ;
Debug.Assert(1 == GetIndexOf('B', StringComparison.InvariantCultureIgnoreCase));
Debug.Assert(null == GetIndexOf('3', StringComparison.InvariantCultureIgnoreCase));
And, you do have to decide what you really intend by your ".ToUpper". As a question/code review issue, it's unclear. It would be better to write your question and code (or at least as a code comment) in such a way as it explains what the proper culture is for letter case comparison. You used one that depends on the program's current culture, which is initialized from the user's culture at the time the program started.
I am new to delegates. Today I saw a code on this Link. AS i am new to c# and specially to delegates, i was unable to understand the below code.
public static void Main()
{
Func<String, int, bool> predicate = (str, index) => str.Length == index;
String[] words = { "orange", "apple", "Article", "elephant", "star", "and" };
IEnumerable<String> aWords = words.Where(predicate).Select(str => str);
foreach (String word in aWords)
Console.WriteLine(word);
}
The OutPut of the above code is "star". AS predicate is expecting to parameters but in this case we are not passing any parameters. Your comments will be really appreciated.
So first, there's a function definition:
Func<String, int, bool> predicate = (str, index) => str.Length == index;
which reads as "given a string represented as str and an index represented as index return true if the length of the string is equal to the index otherwise false"
When you come across to the enumerable pipeline:
IEnumerable<String> aWords = words.Where(predicate).Select(str => str);
you pass this function definition above, which is similar to:
words.Where((element, index) => element.Length == index).Select(str => str);
and as you can see only the element "star" meets that criteria, i.e. the "star" has length 4 and its index is also 4.
In regard to your confusion of:
AS predicate is expecting to parameters but in this case we are not
passing any parameters.
Note that when it comes to LINQ, we only specify the "what" and the "how" is an implementation detail. so in the aforementioned code, the Where clause will pass each element and its index to the predicate function.
On another note, the Select is superfluous, just IEnumerable<String> aWords = words.Where(predicate) should shuffice.
Let's start to examine this code from the first line.
Func<String, int, bool> predicate = (str, index) => str.Length == index;
Here we have simply the declaration of a variable named predicate This is a particular kind of variable whose value is a function that receives two parameters of type string and int and it is expected to return a bool. But where is the body of that function? Just after the equals sign. The (str,index) are the parameters and the body is simply a comparison between the length of the parameter str with the value of the parameter index.
=> str.Length == index returns true if the condition matches otherwise returns false
Now that we understand the declaration of the delegate, the next question is where we use it. This is even simpler. We can use it whenever we need a function that matches our delegate.
Now there is an overload of Where IEnumerable extension that expects just that, so we can simply put the predicate variable in that place and call the Where extension
In short, the code just says, "Select all words where the length equals index"
string[] words = { "orange", "apple", "Article", "elephant", "star", "and" };
// select all words where the length equals the index
var aWords = words.Where((str, i) => str.Length == i);
foreach (var word in aWords)
Console.WriteLine(word);
Where<TSource>(IEnumerable<TSource>, Func<TSource,Int32,Boolean>)
Filters a sequence of values based on a predicate. Each element's
index is used in the logic of the predicate function.
Func<T1,T2,TResult> Delegate
Encapsulates a method that has two parameters and returns a value of
the type specified by the TResult parameter.
So the only magic is the Func
Func<String, int, bool> predicate = (str, index) => str.Length == index;
Which (in this case) is just a fancy way of writing
public bool DoSomething(string str, int index)
{
return str.Length == index;
}
In essence its just a delegate, unlike an Action its capable of returning a value
Delegates (C# Programming Guide)
A delegate is a type that represents references to methods with a
particular parameter list and return type. When you instantiate a
delegate, you can associate its instance with any method with a
compatible signature and return type. You can invoke (or call) the
method through the delegate instance.
To simplify it a bit,
var aWords = words.Where(str => str.Length == 4);
is the same as:
Func<string, bool> predicate = str => str.Length == 4;
var aWords = words.Where(predicate);
predicate() executes it, and predicate without () can be used to pass it as parameter to a method.
With local functions (functions that can be declared inside other functions) introduced in C# 7, it can be :
bool predicate(string str) { return str.Length == 4; }
var aWords = words.Where(predicate);
In C#, given the array :
string[] myStrings = new string[] {
"test#test",
"##test",
"######", // Winner (outputs 6)
};
How can I find the maximum number of occurrences that the character # appears in a single string ?
My current solution is :
int maxOccurrences = 0;
foreach (var myString in myStrings)
{
var occurrences = myString.Count(x => x == '#');
if (occurrences > maxOccurrences)
{
maxOccurrences = occurrences;
}
}
return maxOccurrences;
Is their a simplier way using linq that can act directly on the myStrings[] array ?
And can this be made into an extension method that can work on any IEnumerable<string> ?
First of all let's project your strings into a sequence with count of matches:
myStrings.Select(x => x.Count(x => x == '#')) // {1, 2, 6} in your example
Then pick maximum value:
int maximum = myStrings
.Select(s => s.Count(x => x == '#'))
.Max(); // 6 in your example
Let's make an extension method:
public static int CountMaximumOccurrencesOf(this IEnumerable<string> strings, char ch)
{
return strings
.Select(s => s.Count(c => c == ch))
.Max();
}
However there is a big HOWEVER. What in C# you call char is not what you call character in your language. This has been widely discussed in other posts, for example: Fastest way to split a huge text into smaller chunks and How can I perform a Unicode aware character by character comparison? then I won't repeat everything here. To be "Unicode aware" you need to make your code more complicate (please note code is wrote here then it's untested):
private static IEnumerable<string> EnumerateCharacters(string s)
{
var enumerator = StringInfo.GetTextElementEnumerator(s.Normalize());
while (enumerator.MoveNext())
yield return (string)enumerator.Value;
}
Then change our original code to:
public static int CountMaximumOccurrencesOf(this IEnumerable<string> strings, string character)
{
return strings
.Select(s => s.EnumerateCharacters().Count(c => String.Equals(c, character, StringComparison.CurrentCulture))
.Max();
}
Note that Max() alone requires collection to don't be empty (use DefaultIfEmpty() if collection may be empty and it's not an error). To do not arbitrary decide what to do in this situation (throw an exception if it should happen or just return 0) you can may make this method less specialized and leave this responsibility to caller:
public static int CountOccurrencesOf(this IEnumerable<string> strings,
string character,
StringComparison comparison = StringComparison.CurrentCulture)
{
Debug.Assert(character.EnumerateCharacters().Count() == 1);
return strings
.Select(s => s.EnumerateCharacters().Count(c => String.Equals(c, character, comparison ));
}
Used like this:
var maximum = myStrings.CountOccurrencesOf("#").Max();
If you need it case-insensitive:
var maximum = myStrings.CountOccurrencesOf("à", StringComparison.CurrentCultureIgnoreCase)
.Max();
As you can now imagine this comparison isn't limited to some esoteric languages but it also applies to invariant culture (en-US) then for strings that must always be compared with invariant culture you should specify StringComparison.InvariantCulture. Don't forget that you may need to call String.Normalize() also for input character.
You can write something like this. Note the usage of DefaultIfEmpty, to not throw an exception if myStrings is empty, but revert to 0.
var maximum = myStrings.Select(e => e.Count(ee => ee == '#')).DefaultIfEmpty().Max();
You can do that with Linq combined to Regex:
myStrings.Select(x => Regex.Matches(x, "#").Count).max();
let assume we have an array like this:
var caps = new[] { "1512x", "001xx", "27058", "201xx", "4756x" };
(original array is huge and come from another linq query)
What I need is to create a LINQ statement accepting a value and tries to match with one of the values on the foreseen array.
For example if I use "15121" I need to match the "1512x" value on the array and return it.
Obviously, if I use "27058" it finds the exact match and simply return it.
Is it possible in LINQ?
The "wildcard" char on the array is "x", but I can change it.
Thanks in advance!
Valerio
You can use regular expressions:
var value = "15121";
var caps = new[] { "1512x", "001xx", "27058", "201xx", "4756x" };
var match = caps
.FirstOrDefault(c => new Regex("^" + c.Replace("x", "[0-9]") + "$").IsMatch(value));
if (match != null)
Console.WriteLine("{0} matches {1}", value, match);
The "pattern" 001xx is converted into the regular expression ^001[0-9][0-9]$ and so on. Then the first matching regular expressions is found.
But if the caps is huge it might not perform so well because each regular expression has to be compiled and converted into a state machine until a match is found.
Assuming you have a predicate method, something like this (or something equivalent using Regex, as described in another answer):
static bool Match(string pattern, string exact)
{
if(pattern.Length != exact.Length) return false;
for(var i = 0; i < pattern.Length; i++)
if(pattern[i] != exact[i] && pattern[i] != 'x')
return false;
return true;
}
Then the LINQ query can look like this:
var found = caps.Single(x => Match(x, yourSearch));
Is it possible to write the following 'foreach' as a LINQ statement, and I guess the more general question can any for loop be replaced by a LINQ statement.
I'm not interested in any potential performance cost just the potential of using declarative approaches in what is traditionally imperative code.
private static string SomeMethod()
{
if (ListOfResources .Count == 0)
return string.Empty;
var sb = new StringBuilder();
foreach (var resource in ListOfResources )
{
if (sb.Length != 0)
sb.Append(", ");
sb.Append(resource.Id);
}
return sb.ToString();
}
Cheers
AWC
Sure. Heck, you can replace arithmetic with LINQ queries:
http://blogs.msdn.com/ericlippert/archive/2009/12/07/query-transformations-are-syntactic.aspx
But you shouldn't.
The purpose of a query expression is to represent a query operation. The purpose of a "for" loop is to iterate over a particular statement so as to have its side-effects executed multiple times. Those are frequently very different. I encourage replacing loops whose purpose is merely to query data with higher-level constructs that more clearly query the data. I strongly discourage replacing side-effect-generating code with query comprehensions, though doing so is possible.
In general yes, but there are specific cases that are extremely difficult. For instance, the following code in the general case does not port to a LINQ expression without a good deal of hacking.
var list = new List<Func<int>>();
foreach ( var cur in (new int[] {1,2,3})) {
list.Add(() => cur);
}
The reason why is that with a for loop, it's possible to see the side effects of how the iteration variable is captured in a closure. LINQ expressions hide the lifetime semantics of the iteration variable and prevent you from seeing side effects of capturing it's value.
Note. The above code is not equivalent to the following LINQ expression.
var list = Enumerable.Range(1,3).Select(x => () => x).ToList();
The foreach sample produces a list of Func<int> objects which all return 3. The LINQ version produces a list of Func<int> which return 1,2 and 3 respectively. This is what makes this style of capture difficult to port.
In fact, your code does something which is fundamentally very functional, namely it reduces a list of strings to a single string by concatenating the list items. The only imperative thing about the code is the use of a StringBuilder.
The functional code makes this much easier, actually, because it doesn’t require a special case like your code does. Better still, .NET already has this particular operation implemented, and probably more efficient than your code1):
return String.Join(", ", ListOfResources.Select(s => s.Id.ToString()).ToArray());
(Yes, the call to ToArray() is annoying but Join is a very old method and predates LINQ.)
Of course, a “better” version of Join could be used like this:
return ListOfResources.Select(s => s.Id).Join(", ");
The implementation is rather straightforward – but once again, using the StringBuilder (for performance) makes it imperative.
public static String Join<T>(this IEnumerable<T> items, String delimiter) {
if (items == null)
throw new ArgumentNullException("items");
if (delimiter == null)
throw new ArgumentNullException("delimiter");
var strings = items.Select(item => item.ToString()).ToList();
if (strings.Count == 0)
return string.Empty;
int length = strings.Sum(str => str.Length) +
delimiter.Length * (strings.Count - 1);
var result = new StringBuilder(length);
bool first = true;
foreach (string str in strings) {
if (first)
first = false;
else
result.Append(delimiter);
result.Append(str);
}
return result.ToString();
}
1) Without having looked at the implementation in the reflector, I’d guess that String.Join makes a first pass over the strings to determine the overall length. This can be used to initialize the StringBuilder accordingly, thus saving expensive copy operations later on.
EDIT by SLaks: Here is the reference source for the relevant part of String.Join from .Net 3.5:
string jointString = FastAllocateString( jointLength );
fixed (char * pointerToJointString = &jointString.m_firstChar) {
UnSafeCharBuffer charBuffer = new UnSafeCharBuffer( pointerToJointString, jointLength);
// Append the first string first and then append each following string prefixed by the separator.
charBuffer.AppendString( value[startIndex] );
for (int stringToJoinIndex = startIndex + 1; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
charBuffer.AppendString( separator );
charBuffer.AppendString( value[stringToJoinIndex] );
}
BCLDebug.Assert(*(pointerToJointString + charBuffer.Length) == '\0', "String must be null-terminated!");
}
The specific loop in your question can be done declaratively like this:
var result = ListOfResources
.Select<Resource, string>(r => r.Id.ToString())
.Aggregate<string, StringBuilder>(new StringBuilder(), (sb, s) => sb.Append(sb.Length > 0 ? ", " : String.Empty).Append(s))
.ToString();
As to performance, you can expect a performance drop but this is acceptable for most applications.
I think what's most important here is that to avoid semantic confusion, your code should only be superficially functional when it is actually functional. In other words, please don't use side effects in LINQ expressions.
Technically, yes.
Any foreach loop can be converted to LINQ by using a ForEach extension method,such as the one in MoreLinq.
If you only want to use "pure" LINQ (only the built-in extension methods), you can abuse the Aggregate extension method, like this:
foreach(type item in collection { statements }
type item;
collection.Aggregate(true, (j, itemTemp) => {
item = itemTemp;
statements
return true;
);
This will correctly handle any foreach loop, even JaredPar's answer. EDIT: Unless it uses ref / out parameters, unsafe code, or yield return.
Don't you dare use this trick in real code.
In your specific case, you should use a string Join extension method, such as this one:
///<summary>Appends a list of strings to a StringBuilder, separated by a separator string.</summary>
///<param name="builder">The StringBuilder to append to.</param>
///<param name="strings">The strings to append.</param>
///<param name="separator">A string to append between the strings.</param>
public static StringBuilder AppendJoin(this StringBuilder builder, IEnumerable<string> strings, string separator) {
if (builder == null) throw new ArgumentNullException("builder");
if (strings == null) throw new ArgumentNullException("strings");
if (separator == null) throw new ArgumentNullException("separator");
bool first = true;
foreach (var str in strings) {
if (first)
first = false;
else
builder.Append(separator);
builder.Append(str);
}
return builder;
}
///<summary>Combines a collection of strings into a single string.</summary>
public static string Join<T>(this IEnumerable<T> strings, string separator, Func<T, string> selector) { return strings.Select(selector).Join(separator); }
///<summary>Combines a collection of strings into a single string.</summary>
public static string Join(this IEnumerable<string> strings, string separator) { return new StringBuilder().AppendJoin(strings, separator).ToString(); }
In general, you can write a lambda expression using a delegate which represents the body of a foreach cycle, in your case something like :
resource => { if (sb.Length != 0) sb.Append(", "); sb.Append(resource.Id); }
and then simply use within a ForEach extension method. Whether this is a good idea depends on the complexity of the body, in case it's too big and complex you probably don't gain anything from it except for possible confusion ;)