简体   繁体   中英

Ordering a List by string to find the newer version C#

I have a folder with several Directories that are named after a version of an update such as UPDATE_20080311_3.5.9. I need to find the latest update on that list by veryfing the "3.5.9", I made a code to parse the name and add just the version to a list. Is there anyway to Sort tha list by using List.Sort in order to get the latest version "number"? This is the code I made so far, I don't know how to properly use the .Sort() method and if this can be done. I appreciate any help given

public string NewerVersion(string Directoria)
    {
        List<string> Lista = new List<string>();
        DirectoryInfo dir = new DirectoryInfo(Directoria);
        DirectoryInfo[] dirs = dir.GetDirectories();
        foreach (DirectoryInfo Info in dirs)
        {
            string Dir = Info.Name.ToString();
            Lista.Add(Dir.Substring(Dir.LastIndexOf('_'), Dir.Length));

        }
        Lista.Sort()
        //Lista.ToArray();
    }

You can use Version which implements IComparable , so it supports sorting.

For example with this LINQ query:

Version version = null;
Version lastVersion = new DirectoryInfo(Directoria).EnumerateDirectories()
    .Where(d => d.Name.StartsWith("UPDATE_"))
    .Select(d => new {Directory = d, Token = d.Name.Split('_')})
    .Where(x => x.Token.Length == 3 && Version.TryParse(x.Token[2], out version))
    .Select(x => new {x.Directory, Date = x.Token[1], Version = version})
    .OrderByDescending(x => x.Version)
    .Select(x => x.Version)
    .FirstOrDefault();
string latestVersion = lastVersion.ToString(); // if you want it as string

After I find the newer version I need to be able to return the name of the directory

Then use this query:

var lastVersion = new DirectoryInfo(Directoria).EnumerateDirectories()
    .Where(d => d.Name.StartsWith("UPDATE_"))
    .Select(d => new {Directory = d, Token = d.Name.Split('_')})
    .Where(x => x.Token.Length == 3 && Version.TryParse(x.Token[2], out version))
    .Select(x => new {x.Directory, Date = x.Token[1], Version = version})
    .OrderByDescending(x => x.Version)
    .FirstOrDefault();
if (lastVersion != null)
    Console.WriteLine(lastVersion.Directory.FullName);

When sorting by version , try using Version which is specially designed for that:

 List<String> Lista = new List<string>() {
    "UPDATE_20080311_3.5.9",
    "UPDATE_20080311_3.5.10",
    "UPDATE_20080311_3.4.11",
  };

  Lista.Sort((left, right) => {
    Version x = new Version(left.Substring(left.LastIndexOf('_') + 1));
    Version y = new Version(right.Substring(right.LastIndexOf('_') + 1));

    // or "return -x.CompareTo(y);" if you want to sort in descending order
    return x.CompareTo(y);
  });

  ...

  // UPDATE_20080311_3.4.11
  // UPDATE_20080311_3.5.9
  // UPDATE_20080311_3.5.10
  Console.Write(String.Join(Environment.NewLine, Lista);

Edit:

Continuing from your solution, there is a problem which the way you add your item:

string Dir = Info.Name.ToString();
Lista.Add(Dir.Substring(Dir.LastIndexOf('_'), Dir.Length));

Notice two mistakes here:

  1. You get the Substring from LastIndexOf('_') instead of from LastIndexOf('_') + 1 , which is what you really want
  2. You use Dir.Length while you should use Dir.Length - LastIndexOf('_') + 1 instead

Change that into:

string Dir = Info.Name.ToString();
int indexStart = Dir.LastIndexOf('_') + 1;
Lista.Add(Dir.Substring(indexStart, Dir.Length - indexStart));

Then you could further process the Lista that you have populated to have the version number alone by LINQ OrderBy and ThenBy as well as string.Split('.')

var result = Lista.Select(x => x.Split('.'))
    .OrderBy(a => Convert.ToInt32(a[0]))
    .ThenBy(a => Convert.ToInt32(a[1]))
    .ThenBy(a => Convert.ToInt32(a[2]))
    .Last();
string finalVersion = string.Join(".", result);

To get the final version among the listed items.

To get your directory path back based on your finalVersion , simply do:

string myDirPath = dirs.Select(x => x.FullName).SingleOrDefault(f => f.EndsWith(finalVersion));

You can use Linq and Version

public string NewerVersion(string Directoria)
{
    return new DirectoryInfo(Directoria)
        .GetDirectories()
        .OrderByDescending(x => new Version(x.Name.Substring(x.Name.LastIndexOf('_') + 1)))
        .First()
        .Name;
}

If Directoria contains "UPDATE_20080311_3.5.9", "UPDATE_20090311_5.6.11", "UPDATE_20070311_1.5.9" , will return "UPDATE_20090311_5.6.11"

I'm not sure about, whether this satisfies the requirement or not;if not please forgive me;

You are creating folders for each version release; so a version 3.5.7 will be created after 3.5.6 which is followed by 3.55 and the next version could be 3.58 , So what i'am trying to say is that, they can be sorted on the basics of creation time. if so the following code will help you:

public static string NewerVersion(string Directoria)
{
    List<string> Lista = new List<string>();
    DirectoryInfo dir = new DirectoryInfo(Directoria);
    DirectoryInfo[] dirs = dir.GetDirectories();
    Lista = dirs.OrderBy(x => x.CreationTime).Select(y => y.Name.ToString()).ToList();
    //Lista will contains the required names
    //rest of code here
    return String.Join(Environment.NewLine, Lista);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM