3
\$\begingroup\$

All, I have written some code to get the latest files from a directory, the files I am looking for contain the string sProcScript = "sProcScript" and in the selected directory I might have several versions:

sProcScriptBigGuns1001.sql
sProcScriptBigGuns1007.sql
sProcScriptEdAggVal1006.sql
sProcScriptEdAggVal1007.sql
...

and I want to pick up the latest version only (the version number being the number after the file name i.e. 1007 etc.). So in the above this would be sProcScriptBigGuns1007.sql and sProcScriptEdAggVal1007.sql. To do this I wrote the following snippet (as part of a larger method), where strPath is the path to the relevant directory

DirectoryInfo dirInfo = new DirectoryInfo(strPath);
List<FileInfo> listFileInfo = new List<FileInfo>();
listFileInfo = dirInfo.EnumerateFiles().ToList<FileInfo>();
// Loop in to locate special processes.
List<FileInfo> specialProcList = new List<FileInfo>();
foreach (FileInfo fi in listFileInfo)
 if (Path.GetFileNameWithoutExtension(fi.FullName).Contains(sProcScript))
 specialProcList.Add(fi);
// Get distinct.
List<string> nameList = new List<string>();
foreach (FileInfo fi in specialProcList)
{
 string strsProc = 
 Path.GetFileNameWithoutExtension(Regex.Replace(fi.Name, @"[\d]", String.Empty));
 if (!nameList.Contains(strsProc))
 nameList.Add(strsProc);
}
List<FileInfo> tmpList;
List<string> tmpNameList = new List<string>();
tmpList = specialProcList.OrderByDescending(f => f.Name).ToList();
foreach (string name in nameList)
{
 foreach (FileInfo fi in tmpList)
 {
 if (fi.Name.Contains(name))
 {
 tmpNameList.Add(fi.Name);
 listFilesFound.Add(fi);
 break;
 }
 }
}

which works great. However, I think there will be a much better and neater way of doing this using LINQ but I am new to LINQ and can't seem to get started with it (the attempts I have made are poor enough to not want to post them here!). Can someone demonstate a better way of doing the above operation using LINQ?

Thanks for your time.

palacsint
30.3k9 gold badges82 silver badges157 bronze badges
asked Jul 10, 2012 at 14:06
\$\endgroup\$
2
  • \$\begingroup\$ This is not a code review question. I have demonstrated a viable solution to illustrate I don't want the work done for me. The question could be answered without the code snippet. \$\endgroup\$ Commented Jul 10, 2012 at 14:12
  • \$\begingroup\$ This is part of even larger method? I think writing smaller methods would make your code more readable. \$\endgroup\$ Commented Jul 10, 2012 at 15:04

4 Answers 4

2
\$\begingroup\$

Another one (assuming the filename is always SomeCharactersSomeNumbers.extension):

void Main()
{
 var sProcScript = "sProcScript";
 var fileNames = new [] {"sProcScriptBigGuns1001.sql", 
 "sProcScriptBigGuns1007.sql",
 "sProcScriptEdAggVal1006.sql",
 "sProcScriptEdAggVal1007.sql"};
 var grouped = from f in fileNames
 where f.Contains(sProcScript)
 let m = new {FileName = f, 
 Group = new string(f.TakeWhile(c=>!Char.IsDigit(c)).ToArray()),
 Version = Int32.Parse(new string(f.Where(c=>Char.IsDigit(c)).ToArray()))}
 group m by m.Group;
 var files = grouped.Select(g => g.OrderByDescending(f => f.Version).First().FileName); 
 foreach (var file in files)
 Console.WriteLine(file);
}
answered Jul 10, 2012 at 14:26
\$\endgroup\$
2
\$\begingroup\$

This should do it:

var selectedFileInfos = listFileInfo
 .Where(x => { 
 var filename = Path.GetFileNameWithoutExtension(x.FullName); 
 return specialProcList.Any(y => filename.Contains(y);})
 .OrderByDescending(x => x.Name)
 .GroupBy(x => Path.GetFileNameWithoutExtension(Regex.Replace(x.Name, @"[\d]", String.Empty)) 
 .Select(x => x.First());

But be careful: file numbers should be padded with zeros. 0001, 0900, 0999, 1000, 1001. If they are just normally numbered with 1, 900, 999, 1000 etc., even your code will fail.

answered Jul 10, 2012 at 14:17
\$\endgroup\$
1
  • \$\begingroup\$ Thanks very much, however the edit to you answer was required to get it to work. The edit compiles but returns nothing - can you advise. Again, thanks very much for your time... \$\endgroup\$ Commented Jul 10, 2012 at 14:30
2
\$\begingroup\$

Try:

Directory.EnumerateFiles(filePath)
 .Select(f => new { FileName = f, SprocName = regex.Replace(Path.GetFileNameWithoutExtension(f), ""), Version = int.Parse(regex.Match(f).Value) })
 .Where(f => f.FileName.Contains(sProcScript))
 .GroupBy(f => f.SprocName)
 .Select(g => new { Sproc = g.Key, MaxVersion = g.Max(s => s.Version) })
 .Dump();
answered Jul 10, 2012 at 14:37
\$\endgroup\$
2
\$\begingroup\$

How about:

var files = from file in new DirectoryInfo(strPath).EnumerateFiles()
 let nameWithoutEx = Path.GetFileNameWithoutExtension(file.Name)
 where nameWithoutEx.Contains(sProcScript)
 let key = new string(nameWithoutEx.Reverse()
 .SkipWhile(char.IsDigit)
 .Reverse()
 .ToArray())
 group file by key into versionGroup
 select versionGroup
 .OrderBy(f => int.Parse(new string(f.Name
 .Skip(versionGroup.Key.Length)
 .TakeWhile(char.IsDigit)
 .ToArray())))
 .Last();
answered Jul 10, 2012 at 14:29
\$\endgroup\$
4
  • \$\begingroup\$ Thanks but as this stands it won't compile due to a number of errors. Thanks for your time... \$\endgroup\$ Commented Jul 10, 2012 at 14:43
  • \$\begingroup\$ @Killercam: Didn't try, but what are the errors? What version of C# / .NET are you on? \$\endgroup\$ Commented Jul 10, 2012 at 14:45
  • \$\begingroup\$ Framework 4.0, there were a few. I have an answer above working so I wont waste anymore of your time. But thanks you very much for your response it is most appreciated. \$\endgroup\$ Commented Jul 10, 2012 at 14:50
  • \$\begingroup\$ @Killercam: The only thing missing was the ToArray() calls. Fine now. \$\endgroup\$ Commented Jul 10, 2012 at 14:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.