Using StringComparison.OrdinalIgnoreCase to ignore Case - linq

This code is case sensitive, how to make it case insensitive?
return HeaderNames.Length == fileLine.Count &&
HeaderNames
.Select(headItem => fileLine[Array.IndexOf(HeaderNames, headItem)] == headItem)
.All(i => i);
Thanks for your answers/

How about using FindIndex instead of IndexOf.
I assume you have array of strings
Array.FindIndex(HeaderNames, t => t.IndexOf(headItem, StringComparison.InvariantCultureIgnoreCase) >=0);
Example:
var a = new string[]{"green","red"};
var idx = Array.FindIndex(a, t => t.IndexOf("Red", StringComparison.InvariantCultureIgnoreCase) >=0);
Console.WriteLine(idx);
Output
1
Note: You could also use string.Equals instead of t.IndexOf in above suggestion
t=>string.Equals(t, headItem, StringComparison.InvariantCultureIgnoreCase)
It will be a long nested LINQ though.
Edit
If you want to find exact string i.e. dont want to get index of «ed» from «Red» as item existing in array. Use string.Equals.

There is no reason to index back into the array to get the position, there is a version of Select for that. You can use String.Equals and pass the StringComparison option:
return HeaderNames.Length == fileLine.Count &&
HeaderNames.Select((headItem, i) => fileLine[i].Equals(headItem, StringComparison.OrdinalIgnoreCase)).All(i => i);

Related

Using Linq, How can I properly append multiple Where clauses so that they appear in the appropriate order?

The order I would like the end result to appear in is Exact Matches first given a input string, followed by other matches that are Contains for a given field. I tried to approach this in a very rudimentary way as shown here in this example:
var raw = Model.SearchResults.Where(m => m.EffectiveDateTime != null).OrderBy(m => m.EffectiveDateTime).ToList();
var exact = raw.Where(m => m.IssueNumber.ToLower() == Model.SearchText.ToLower());
var contains = raw.Where(m => m.IssueNumber.ToLower().Contains(Model.SearchText.ToLower()));
var list = exact.Union(contains);
This approach seems like it'd be a really bad way to do this. In fact, the Union portion seems to effectively crash my application. Is there an opposite to Intersection which would give me the remaining results outside the Exact matches that I could then append to a final list so that the order would be Exact Matches followed by StartsWith matches followed finally by Contains matches in that descending order?
To answer your original question, you can use a temporary expression to classify the match types, then order by the match type and other criteria, and it will translate to SQL as well:
var st = Model.SearchText.ToLower();
var list = Model.SearchResults.Where(m => m.EffectiveDateTime != null)
.Select(m => new {
m,
im = m.IssueNumber.ToLower()
})
.Select(mim => new {
mim.m,
Rank = mim.im == st ? 1 : mim.im.StartsWith(st) ? 2 : mim.im.Contains(st) ? 3 : 4
})
.Where(mr => mr.Rank < 4)
.OrderBy(mr => mr.Rank)
.ThenBy(mr => mr.m.EffectiveDateTime)
.Select(mr => mr.m)
.ToList();
I did the double Select to emulate let from fluent syntax, which I think is a bit clearer than lambda syntax in this case:
var lisx = (from m in Model.SearchResults
where m.EffectiveDateTime != null
let im = m.IssueNumber.ToLower()
let Rank = im == st ? 1 : im.StartsWith(st) ? 2 : im.Contains(st) ? 3 : 4
where Rank < 4
orderby Rank, m.EffectiveDateTime
select m)
.ToList();
Also, if you do the whole query in the database, the ToLower is likely unnecessary, as the default for SQL is probably to be case-insensitive anyway.
Actually, I went back to the drawing board and figured it out. This is a little bit better for me and returns the results I needed.
var list = Model.SearchResults
.Where(e => e.A.ToLower().Contains(Model.SearchText.ToLower()))
.GroupBy(d => new { d.A, d.B, d.C})
.OrderBy(x => x.Key.A)
.ThenBy(x => x.Key.B)
.ThenBy(x => x.Key.C)
.Select(x => new
{
A= x.Key.A,
B= x.Key.B,
C= x.Key.C
})
.ToList();

Equivalent of Right() function

Is there an equivalent of right() function that I can use in jquery. I want to get records with fileextension xlsx.
new Guid(context.Documents.Where(T => T.FileName == ".xlsx").Select(T => T.ItemGuid).First().ToString());
something like
select * from document where right(filename,4) = 'xlsx'
I don't want to store the filename in a variable and later manipulate it. I want to be able to directly use it in my where condition. 'Documents' is my table name and "FileName" is a field that holds names of the file that I upload, now I need to get filter only the files that has the extension 'xlsx'. I tried doing
guid temp = new Guid(context.Documents.Where(T => T.FileName.Substring(T.FileName.Length - 4) == ".xlsm").Select(T => T.ItemGuid).First().ToString());
but I get the error "Sequence contains no elements" error.
* Update: Used the EndsWith() to get the information I wanted. This works now:
guid temp = new Guid(context.Documents.Where(T => T.FileName.EndsWith("xlsm")).Select(T => T.ItemGuid).First().ToString());
thanks.
filename.substr(-4)
Using .substr with a negative index will return a substring from the end of the string.
You can use .slice (MDN) function, taking into account that passing a negative value into it makes it cut the string from the end. )
var test = 'filename.xslx';
if (test.slice(-4) === 'xslx') {
alert("Passed");
}
right() is the same as endswith()
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
You might be looking for [name$="value"] selector documented here.
There is not, you can use
var filename = "file.xlsx";
var extension = filename.substr(filename.length - 4);
or to get the characters after the dot, you could use:
var extension = filename.split('.').pop();
Use could javascript match() which provides regex matching.
var filename = 'somefile.xlsx';
var matches = filename.match('/\.xlsx$/i');
if (matches.length > 0) {
// you have a match
}

LINQ read Select values

I have a LINQ query where I want to select and read the p.Api value.
var api = DataAccessNew.Instance.dcServers.Where(p => p.Ip == IpAddress).Select(p => p.Api);
How do I read the p.Api value?
I have tried api.ToString() but I get SQL instead of actual column value.
You are getting an IEnumerable<> back (and your ToString call is showing you the value of that expression).
If you are expecting a single value, do this:
var api = DataAccessNew.Instance.dcServers
.Where(p => p.Ip == IpAddress)
.Select(p => p.Api)
.Single();
You might be interested to read about the other methods like Single(): SingleOrDefault, First, FirstOrDefault. Which one you used depends on whether you are expecting a single or multiple values returned (Single vs. First) and what you want to happen if there are no values (the *Default methods will return the type default instead of throwing an exception).
Or if you want to look at all the returned values:
var api = DataAccessNew.Instance.dcServers
.Where(p => p.Ip == IpAddress)
.Select(p => p.Api);
foreach (var apiValue in api)
{
// apiValue will have the value you're looking for.
}
Try this snippet of code:
string apiValue = api.FirstOrDefault().ToString();
your syntex seems ok..
By the way try this
string api =DataAccessNew.Instance.dcServers.Where(p => p.Ip == IpAddress).Select(p => p.Api).FirstOrDefault();
if p.Ip is a unique key in your table you could try to add .FirstOrDefault() after your Linq query.
public string getselectedvalue(ListBox l)
{
string vtext="",vval="";
var selectedQueryText = l.Items.Cast<ListItem>().Where(item => item.Selected);
var selectedQueryVal = l.Items.Cast<ListItem>().Where(item => item.Selected).Select(item => item.Value);
vtext= String.Join("','", selectedQueryText ).TrimEnd();
vval= String.Join("','", selectedQueryVal ).TrimEnd();
return v;
}

Convert an ordinary LINQ query to lambda expression

from _tupleRows in this.TupleSet
from _member in _tupleRows.Members
where (_member.HasChildMembers && !_member.DrilledDown)
select new
{
_member1 = _member,
_member2 = (from _searched in this.TupleSet
from _compareMember in _searched.Members
where (_member.UniqueName == _compareMember.UniqueName &&
_member.LevelDepth == _compareMember.LevelDepth &&
_compareMember.DrilledDown)
select _compareMember).FirstOrDefault()
};
I need to convert this simple LINQ expression to an equivalent lambda expression
from _tupleRows in this.TupleSet
from _member in _tupleRows.Members
where (_member.HasChildMembers && !_member.DrilledDown)
select new
{
_member1 = _member,
_member2 = (from _searched in this.TupleSet
from _compareMember in _searched.Members
where (_member.UniqueName == _compareMember.UniqueName
&& _member.LevelDepth == _compareMember.LevelDepth
&& _compareMember.DrilledDown)
select _compareMember).FirstOrDefault()
};
becomes:
this.TupleSet
.SelectMany(tupleRows =>
tupleRows.Members
.Where(member => member.HasChildMembers && !member.DrilledDown)
.Select(member => new
{
_member1 = member,
_member2 = this.TupleSet
.SelectMany(searched =>
searched.Members
.Where(compareMember =>
member.UniqueName == compareMember.UniqueName
&& member.LevelDepth == compareMember.LevelDepth
&& compareMember.DrilledDown))
.FirstOrDefault(),
}));
They're really not hard to convert. Just start at the top and append as you go.
Something like:
this.TupleSet.SelectMany(ts => ts.Members)
.Where(m => m.HasChildMembers && !m.DrilledDown)
.Select(m => new
{
_member1 = m,
_member2 = this.TupleSet.SelectMany(ts => ts.Members)
.Where(other => m.UniqueName == other.UniqueName
&& m.LevelDepth == other.LevelDepth
&& other.DrilledDown
)
.FirstOrDefault()
});
No guarantees this is perfect or will even compile, but then I'm not trying to do your work for you, I'm trying to give you a demonstration of how you might do these conversions yourself.
Also, do yourself a favor and use simpler identifiers in lambdas when you can. They're very limited scope, and you're chaining calls to make one big statement, so often it will usually be very obvious in context what a variable means. I may not have the best example here, but the original variable names were way too verbose, IMO.
The nested query also seems a little strange. If there is a way to structure your data so you don't have to do that nested query I think you'll get better perf and simpler queries.

Better way to check resultset from LINQ projection than List.Count?

Is there a better way to check if a LINQ projection query returns results:
IList<T> TList = db.Ts.Where(x => x.TId == 1).ToList(); // More canonical way for this?
if (TitleList.Count > 0)
{
// Result returned non-zero list!
string s = TList.Name;
}
You can use Any(), or perhaps more appropriately to your example, SingleOrDefault(). Note that if you are expecting more than one result and plan to use all of them, then it doesn't really save anything to use Any() instead of converting to a List and checking the length. If you don't plan to use all the results or you're building a larger query that might change how the query is performed then it can be a reasonable alternative.
var item = db.Ts.SingleOrDefault( x => x.TId == 1 );
if (item != null)
{
string s = item.Name;
...
}
or
var query = db.Ts.Where( x => x.Prop == "foo" );
if (query.Any())
{
var moreComplexQuery = query.Join( db.Xs, t => t.TId, x => x.TId );
...
}

Resources