0

I have a list of type string. Each string is a full path to a file. Now I would like to sort this list by the name of the file.

When I use the Sort() method, the list would be sorted by the full path. But the path can be different.

Is there a simple way to sort the list by whats left after the last \ of each item?

5 Answers5

8

You can use System.IO.Path.GetFileName and LINQ:

files = files.OrderBy(System.IO.Path.GetFileName).ToList();

If you want to compare in a case-insensitive manner you can pass a StringComparer:

files = files.OrderBy(System.IO.Path.GetFileName, StringComparer.InvariantCultureIgnoreCase).ToList();

Note that OrderBy (and OrderByDescending) uses a stable sort algorithm as opposed to List.Sort. That means that all elements which are equal stay in the original order.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Also it is likely that the list of files can be obtained from `Directory.EnumerateFiles()` which can be used with `OrderBy` - in which case this saves temporarily storing the files in a list or array before sorting them. – Matthew Watson Nov 23 '16 at 09:07
3

You're looking for Path.GetFileName:

https://msdn.microsoft.com/en-us/library/system.io.path.getfilename(v=vs.110).aspx

   List<string> files = ...

   // when sorting via Sort we should compare file names
   files.Sort((left, right) => 
     string.Compare(Path.GetFileName(left), Path.GetFileName(right)));

The advantages of Sort over Linq OrderBy are

  • Sort performs in place sorting when Linq creates an additional collection via .ToList()
  • You can put a complex sorting algorithm just within the lambda function; in case of Linq one has to implement IComparer<T> interface

The disadvantages are

  • Linq wants just IEnumerable<T> when Sort requires List<T>.
  • Sort() uses unstable sorting algorithms (if two items considered being equal their actual order in the sorted list is not guaranteed)
  • current simplest implementtation string.Compare(Path.GetFileName(left), Path.GetFileName(right)) calls Path.GetFileName too often (about twice as many as OrderBy)
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • This attempt works better than the others since you can explicitly specify the CultureInfo and CompareOptions, e.g. `String.Compare(Path.GetFileName(left), Path.GetFileName(right), CultureInfo.InvariantCulture, CompareOptions.Ordinal)` – Manfred Radlwimmer Nov 23 '16 at 08:51
  • @Manfred Radlwimmer: another advantage is that `Sort` sorts the list *in place* unlike Linq which creates an additional collection – Dmitry Bychenko Nov 23 '16 at 08:52
  • @ManfredRadlwimmer: you can use the overload of `OrderBy` to pass a `StringComparer`. I've edited [my answer](http://stackoverflow.com/a/40759683/284240) accordingly. – Tim Schmelter Nov 23 '16 at 08:57
  • A major disadvantage of this over using `OrderBy()` is that `Path.GetFileName()` will be called twice for each comparison, while `OrderBy` only calls it once for each item in the list. The number of comparisons can greatly outnumber the number of items in the list. – Matthew Watson Nov 23 '16 at 09:01
  • Another disadvantage is that `List.Sort` performs an unstable whereas `Enumerable.OrderBy` a stable sort. So equal items remain in their original order. – Tim Schmelter Nov 23 '16 at 09:04
1

this example code,

 var getFileName = System.IO.Path.GetFileName("C:\temp\name.txt"); > temp.txt

 var getfileNameWithoutExtention = System.IO.Path.GetFileName("C:\temp\name.txt"); > name

 var getextention = System.IO.Path.GetFileName("C:\temp\name.txt"); > .txt



 List<string> patsh = new List<string>
        {
            @"C:\temp\name.txt",
            @"C:\music\ranbow.mp3",
            @"C:\net\core.cs",
            @"C:\java\fr.jar"
        };



 patsh = patsh.OrderBy(System.IO.Path.GetFileNameWithoutExtension).ToList();

if you want to do it with file extension

 patsh = patsh.OrderBy(System.IO.Path.GetFileNameWithoutExtension).ThenBy(System.IO.Path.GetExtension).ToList();
go..
  • 958
  • 7
  • 15
0

This might do the trick for you

List<string> fullfilepath = new List<string>() { "C:\\text1.txt", "C:\\text2.txt", "D:\\text4.txt", "C:\\text3.txt", "C:\\text6.txt", "D:\\text5.txt" };
List<string> sortedfilename = fullfilepath.OrderBy(x => Path.GetFileName(x)).ToList();
Mohit S
  • 13,723
  • 6
  • 34
  • 69
-1

You can also sort it by fileName like this:

fileName = path.Split('\').Last();
Aviv
  • 58
  • 5