0

I want to sort the files of folder in the ascending order so that I can combine that files properly but the output I am getting is, 1,10,11 like wise and I want the output as, 1,2,3.. like wise. I am using this,

                DirectoryInfo di = new DirectoryInfo(source_path);
                FileInfo[] arrFi = di.GetFiles("*.*");
                //arrFi.OrderBy(fi=>fi.LastWriteTime);
                Array.Sort(arrFi.OrderBy(fi => fi.LastWriteTime));
Mansi
  • 11
  • 1
  • Do you want to sort files by their *write times* or by their *names*? – Dmitry Bychenko Mar 16 '21 at 09:38
  • You are looking for natural ordering [What is natural ordering?](https://stackoverflow.com/questions/5167928/) . Then you will find how to [Natural Sort Order in C#](https://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp). And [this](https://stackoverflow.com/questions/3716831/), https://stackoverflow.com/questions/8568696/icomparer-for-natural-sorting – Self Mar 16 '21 at 09:42
  • `var arrFi = new DirectoryInfo(source_path).EnumerateFiles("*.*").OrderBy(file => file.LastWriteTime).ToArray();` if you want to sort the files by their last write times – Dmitry Bychenko Mar 16 '21 at 09:42
  • Directory.GetFiles(folder, "*.dll").Select(fn => new FileInfo(fn)).OrderBy(f => f.LastWriteTime); Please check this also https://stackoverflow.com/a/6294337/2638414 – Vijay Maheriya Mar 16 '21 at 11:15

1 Answers1

0

It's unclear what is the desired result looks like. If you want to sort files by their last write time a simple Linq query will do:

  var arrFi = new DirectoryInfo(source_path)
    .EnumerateFiles("*.*")
    .OrderBy(file => file.LastWriteTime)
    .ToArray();

If you want to order files by their names in natural order (i.e. "1" < "5" < "9" < "10" < "12" < "100") the query itself will be as easy as the previous one:

  var arrFi = new DirectoryInfo(source_path)
    .EnumerateFiles("*.*")
    .OrderBy(file => file.Name, new StringNaturalComparer(null))
    .ToArray();

But you have to implement the comparer:

  public sealed class StringNaturalComparer : IComparer<String> {
    private readonly IComparer<string> m_Comparer;

    private static List<string> ToChunks(string value) {
      List<string> result = new();

      StringBuilder sb = null;

      bool isDigit = false;

      foreach (var c in value) {
        if (sb is null) {
          sb = new StringBuilder(value.Length);
          isDigit = char.IsDigit(c);
          sb.Append(c);
        }
        else if (isDigit != char.IsDigit(c)) {
          result.Add(sb.ToString());
          sb.Clear();
          isDigit = char.IsDigit(c);
        }

        sb.Append(c);
      }

      if (sb != null)
        result.Add(sb.ToString());

      return result;
    }

    public StringNaturalComparer(IComparer<string> comparer) {
      m_Comparer = comparer == null ? StringComparer.Ordinal : comparer;
    }

    public int Compare(string left, string right) {
      if (ReferenceEquals(left, right))
        return 0;
      else if (left == null)
        return -1;
      else if (right == null)
        return 1;

      var lefts = ToChunks(left);
      var rights = ToChunks(right);

      int result;

      for (int i = 0; i < Math.Min(lefts.Count, rights.Count); ++i) {
        string leftChunk = lefts[i];
        string rightChunk = rights[i];

        if (char.IsDigit(leftChunk[0]) && char.IsDigit(rightChunk[0])) {
          result = leftChunk.Length.CompareTo(rightChunk.Length);

          if (result != 0)
            return result;
        }

        result = m_Comparer.Compare(leftChunk, rightChunk);

        if (result != 0)
          return result;
      }

      return lefts.Count.CompareTo(rights.Count);
    }
  }
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215