2

I'm retrieving a string array of files and I would like to custom sort them by a substring in the file name...using C# **.NET 3.5. Below is what I am working with.

         <%  string[] files = System.IO.Directory.GetFiles("...path..." + pageName + "\\reference\\");
           files = String.Join(",", files).Replace("...path...", "").Replace("\\reference\\", "").Replace(pageName, "").Split(new Char[] { ',' });
                foreach (String item in files)
                {
                  Response.Write("<a href=" + pageName + "/reference/" + System.IO.Path.GetFileName(item) + " target='_blank'>" + item.Replace("_", "  ").Replace(".pdf", " ") + "</a>");
                }
       %>   

I'm a C# noob, and I don't know where to go from here. Basically, I'm looking for a substring in the file name to determine the order (e.g., "index","reference","list"; where any file including the string "index" would be listed first). Perhaps there is a better way to do it. Any help would be appreciated.

1
  • So "index" is first, "refernce" second and "list" last? Commented Aug 12, 2013 at 20:58

2 Answers 2

2

You can use Linq to order the array by the filenames. In general, use the Path class if you're working with paths.

string fullPath = Path.Combine(directory, pageName, "reference");
var filePaths = Directory.EnumerateFiles(fullPath, "*.*", SearchOption.TopDirectoryOnly)
    .Select(fp => new{ FullPath = fp, FileName=Path.GetFileName(fp) })
    .OrderByDescending(x => x.FileName.IndexOf("index", StringComparison.OrdinalIgnoreCase) >= 0)
    .ThenByDescending(x => x.FileName.IndexOf("reference", StringComparison.OrdinalIgnoreCase) >= 0)
    .ThenByDescending(x => x.FileName.IndexOf("list", StringComparison.OrdinalIgnoreCase) >= 0)
    .ThenBy(x=> x.FileName)
    .Select(x => x.FullPath);
foreach(string filePath in filePaths)
    ;// ...

If you don't want to compare case-insensitively (so that "index" and "Index" are considered the same) use String.Contains instead of String.IndexOf + StringComparison.OrdinalIgnoreCase.

Sign up to request clarification or add additional context in comments.

2 Comments

That looks helpful but unfortunately I am using .net 3.5 which does not include the method 'enumeratefiles'. Sorry for not noting that in the original question. If it were up to me I would upgrade to 4 but it is not my call.
Then use GetFiles instead, the only difference is that this loads all into memory first whereas EnumerateFiles lazily processes the files. Note that i've edited my answer. Now i'm using correctly ThenByDescending instead of OrderByDescending (copy&paste bug).
1

Here's an easy way I use when I run into this problem.

Define the order of the substrings in a list. Then for each item, check to see whats the first thing that contains that item. Then sort by the order of the substring in the list.

public class SubStringSorter : IComparer<string>
{
    public int Compare(string x, string y)
    {
        var source = x.ToLowerInvariant();
        var target = y.ToLowerInvariant();

        var types = new List<string> { "base", "data", "model", "services", "interceptor", "controllers", "directives", "filters", "app", "tests", "unittests" };

        var sourceType = types.IndexOf(types.FirstOrDefault(source.Contains));
        var targetType = types.IndexOf(types.FirstOrDefault(target.Contains));

        return sourceType.CompareTo(targetType);
    }
}

To sort your files, do something like

var list = new List<string>{ "baseFile", "servicesFile", "this ModElstuff"  };

list.Sort(new SubStringSorter());

And the output

enter image description here

You could even go one step further and give the substring sorter the list as part of its constructor so you can re-use the substring sort order with other items. The example I posted tests if the string exists in any context, but if you are more interested in it starting with a string you can do that too.

Comments

Your Answer

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.