Equivalent of Right() function - linq

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
}

Related

Using StringComparison.OrdinalIgnoreCase to ignore Case

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

Delete Files that are more than than 10 days old using Linq

i'm using the code below to delete the files that are more than 10 days old. Is there a simpler/smarter way of doing this?
string source_path = ConfigurationManager.AppSettings["source_path"];
string filename= ConfigurationManager.AppSettings["filename"];
var fileQuery= from file in Directory.GetFiles(source_path,filename,SearchOption.TopDirectoryOnly)
where File.GetCreationTime(file)<System.DateTime.Now.AddDays(-10)
select file;
foreach(var f in fileQuery)
{
File.Delete(f);
}
Well there are two things I'd change:
Determine the cut-off DateTime once, rather than re-evaluating DateTime.Now repeatedly
I wouldn't use a query expression when you've just got a where clause:
So I'd rewrite the query part as:
var cutoff = DateTime.Now.AddDays(-10);
var query = Directory.GetFiles(sourcePath, filename, SearchOption.TopDirectoryOnly)
.Where(f => File.GetCreationTime(f) < cutoff);
Another alternative would be to use DirectoryInfo and FileInfo:
var cutoff = DateTime.Now.AddDays(-10);
var path = new DirectoryInfo(sourcePath);
var query = path.GetFiles(filename, SearchOption.TopDirectoryOnly)
.Where(fi => fi.CreationTime < cutoff);
(In .NET 4 you might also want to use EnumerateFiles instead.)
It is possible to do a LINQ "one-liner" to perform this process:
Directory.GetFiles(source_path,filename,SearchOption.TopDirectoryOnly)
.Where(f => File.GetCreationTime(file) < System.DateTime.Now.AddDays(-10))
.All(f => {File.Delete(f); return true;);
Don't forget to wrap the code in a try catch.

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 );
...
}

Reading Text Files with LINQ

I have a file that I want to read into an array.
string[] allLines = File.ReadAllLines(#"path to file");
I know that I can iterate through the array and find each line that contains a pattern and display the line number and the line itself.
My question is:
Is it possible to do the same thing with LINQ?
Well yes - using the Select() overload that takes an index we can do this by projecting to an anonymous type that contains the line itself as well as its line number:
var targetLines = File.ReadAllLines(#"foo.txt")
.Select((x, i) => new { Line = x, LineNumber = i })
.Where( x => x.Line.Contains("pattern"))
.ToList();
foreach (var line in targetLines)
{
Console.WriteLine("{0} : {1}", line.LineNumber, line.Line);
}
Since the console output is a side effect it should be separate from the LINQ query itself.
Using LINQ is possible. However, since you want the line number as well, the code will likely be more readable by iterating yourself:
const string pattern = "foo";
for (int lineNumber = 1; lineNumber <= allLines.Length; lineNumber++)
{
if (allLines[lineNumber-1].Contains(pattern))
{
Console.WriteLine("{0}. {1}", lineNumber, allLines[i]);
}
}
something like this should work
var result = from line in File.ReadAllLines(#"path")
where line.Substring(0,1) == "a" // put your criteria here
select line

LINQ: Field is not a reference field

I've got a list of IQueryable. I'm trying to split this list into an array of IQueryable matching on a certain field (say fieldnum) in the first list...
for example, if fieldnum == 1, it should go into array[1]. I'm using Where() to filter based on this field, it looks something like this:
var allItems = FillListofMyObjects();
var Filtered = new List<IQueryable<myObject>(MAX+1);
for (var i = 1; i <= MAX; i++)
{
var sublist = allItems.Where(e => e.fieldnum == i);
if (sublist.Count() == 0) continue;
Filtered[i] = sublist;
}
however, I'm getting the error Field "t1.fieldnum" is not a reference field on the if line. stepping through the debugger shows the error actually occurs on the line before (the Where() method) but either way, I don't know what I'm doing wrong.
I'm farily new to LINQ so if I'm doing this all wrong please let me know, thanks!
Why don't you just use ToLookup?
var allItemsPerFieldNum = allItems.ToLookup(e => e.fieldnum);
Do you need to reevaluate the expression every time you get the values?
Why not use a dictionary?
var dictionary = allItems.ToDictionar(y => y.fieldnum);

Resources