2

如何从可用产品版本列表中返回最佳匹配/下一个可用产品 versionId?

这是基于表中示例数据的逻辑

寻找小于 10.10.20 的最佳匹配版本,并应返回其 versionID eg1:GetVersion("10.10.20") 应返回 5(因为在表中没有“10,10,20”major.minor.build 组合可用,所以它应该在这里寻找最匹配的版本下一个可用版本是 10.7.1 即版本 ID 5

eg2:GetVersion("7.0.0") 应该返回 3(因为在表中没有可用的“7,0,0”major.minor.build 组合,所以它应该寻找下一个可用的匹配版本。这里是下一个可用版本是 6.2.1 即版本 ID 3

eg3:GetVersion("7.5.1") 应该返回 4 ,这里完全匹配可用,所以应该返回 versionid 4

 [Serializable]
    public class ProductVersions
    {
        [Key]
        public int Version_Id { get; set; }
        public int Major { get; set; }
        public int Minor { get; set; }
        public int Build { get; set; }
    }

这是我的 ProductVersions 表中的一些示例数据

    [version_id , Major,Minor,Build]
        1           3      0    1
        2           4     10    5
        3           6     2     1
        4           7     5     1
        5           10    7     1
        6           11    10   10

这是我的方法,有望返回最佳可用产品版本

private int GetVersion(string versionNumber)
   {
    int version-id=0;

    version-id= //retrieve best matching version

     return version-id
    }
4

4 回答 4

1

我喜欢多米尼克使用版本类的答案(为什么要在它存在时发明?)但是如果您想知道如何在不使用版本类的情况下做到这一点,并且您假设列表已经排序(因此您不需要排序就像他做的那样)。

(TL;DR)

 // assume verArray is already ordered (this would need to be sorted otherwise.)
 // this where checks for less than or equal to.
 int result = verArray.Where(v => (v.Major < major) ||
                                  (v.Major == major && v.Minor < minor) ||
                                  (v.Major == major && v.Minor == minor && v.Build <= build))
                      .Last().Version_Id;

完整代码和测试:

public ProductVersions[]verArray = {
      new ProductVersions() { Version_Id = 1, Major = 3, Minor = 0, Build = 1 },
      new ProductVersions() { Version_Id = 2, Major = 4, Minor = 10, Build = 5 },
      new ProductVersions() { Version_Id = 3, Major = 6, Minor = 2, Build = 1 },
      new ProductVersions() { Version_Id = 4, Major = 7, Minor = 5, Build = 1 },
      new ProductVersions() { Version_Id = 5, Major = 10, Minor = 7, Build = 1 },
      new ProductVersions() { Version_Id = 6, Major = 11, Minor = 10, Build = 10 },
  };

void Main()
{
  string test = "10.10.20";
  Console.WriteLine(test + " gives "+GetVersion(test));

  test = "7.0.0";
  Console.WriteLine(test + " gives "+GetVersion(test));

  test = "7.5.1";
  Console.WriteLine(test + " gives "+GetVersion(test));
}

private int GetVersion(string versionNumber)
{
  string [] input = versionNumber.Split(".".ToCharArray());

  int major = int.Parse(input[0]);
  int minor = int.Parse(input[1]);
  int build = int.Parse(input[2]);

  // assume verArray is already ordered (this would need to be sorted otherwise.
  int result = verArray.Where(v => (v.Major < major) ||
                                   (v.Major == major && v.Minor < minor) ||
                                   (v.Major == major && v.Minor == minor && v.Build <= build))
                       .Last().Version_Id;

  return result;
}

public class ProductVersions
{
  public int Version_Id { get; set; }
  public int Major { get; set; }
  public int Minor { get; set; }
  public int Build { get; set; }
}

这将返回以下内容:

10.10.20 gives 5
7.0.0 gives 3
7.5.1 gives 4
于 2013-09-10T14:04:11.437 回答
1

您可以使用内置的 Version 类,因为它已经实现了<=您基本上正在寻找的运算符,并且还可以为您处理字符串解析:

var data = new List<Version>()
{
     new Version(3,0,1),
     new Version(4,10,5),
     new Version(6,2,1),
     new Version(7,5,1),
     new Version(10,7,1),
     new Version(11,10,10)
};

var case1 = new Version("10.10.20");
// match1 is 5; the index of a List is 0-based, so we add 1
var match1 = data.FindLastIndex(d => d <= case1) + 1;

var case2 = new Version("7.0.0");
// match2 is 3
var match2 = data.FindLastIndex(d => d <= case2) + 1;

var case3 = new Version("7.5.1");
// match3 is 4
var match3 = data.FindLastIndex(d => d <= case3) + 1;

将您的序列转换ProductVersionsVersion对象列表应该很简单。

如果您出于某种原因不想使用Version该类,则可以自己实现<=(以及所有其他缺少的运算符):

public class ProductVersions
{
   //TODO error checking
   public int Version_Id { get; set; }
   public int Major { get; set; }
   public int Minor { get; set; }
   public int Build { get; set; }

   public ProductVersions(int major, int minor, int build)
   {
        Major=major;
        Minor=minor;
        Build=build;
   }

   public ProductVersions(string version)
   {
        var tmp = version.Split('.');
        Major = Int32.Parse(tmp[0]);
        Minor = Int32.Parse(tmp[1]);
        Build = Int32.Parse(tmp[2]);
   }

   public static bool operator == (ProductVersions a, ProductVersions b)
   {
        return a.Major==b.Major && a.Minor==b.Minor && a.Build==b.Build;
   }

   public static bool operator != (ProductVersions a, ProductVersions b)
   {
        return !(a==b);
   }

   public static bool operator <= (ProductVersions a, ProductVersions b)
   {
        if (a == b)
            return true;
        return a < b;
   }

   public static bool operator >= (ProductVersions a, ProductVersions b)
   {
        if (a == b)
            return true;
        return a > b;
   }

   public static bool operator < (ProductVersions a, ProductVersions b)
   {
        if(a.Major==b.Major)
            if(a.Minor==b.Minor)
                return a.Build < b.Build;
            else
                return a.Minor < b.Minor;
        else
            return a.Major < b.Major;
   }

   public static bool operator > (ProductVersions a, ProductVersions b)
   {
        if(a.Major==b.Major)
            if(a.Minor==b.Minor)
                return a.Build > b.Build;
            else
                return a.Minor > b.Minor;
        else
            return a.Major > b.Major;
   }

和一个简单的测试:

var data = new List<ProductVersions>()
{
     new ProductVersions(3,0,1)    { Version_Id = 1},
     new ProductVersions(4,10,5)   { Version_Id = 2},
     new ProductVersions(6,2,1)    { Version_Id = 3},
     new ProductVersions(7,5,1)    { Version_Id = 4},
     new ProductVersions(10,7,1)   { Version_Id = 5},
     new ProductVersions(11,10,10) { Version_Id = 6}
};

// ensure data is sorted by version
data.Sort((a,b) => a > b ? 1 : a < b ? -1 : 0);

var case1 = new ProductVersions("10.10.20");
// match1 is 5
var match1 = data.Last(d => d <= case1).Version_Id;

var case2 = new ProductVersions("7.0.0");
// match2 is 3
var match2 = data.Last(d => d <= case2).Version_Id;

var case3 = new ProductVersions("7.5.1");
// match3 is 4
var match3 = data.Last(d => d <= case3).Version_Id;
于 2013-09-10T13:43:29.453 回答
-3

我刚刚检查了你提供的样品。这段代码对我有用。

private int getver(int m, int n, int b)
{
    List<ProductVersions> pv = new List<ProductVersions>();
    pv.Add(new ProductVersions { Version_Id = 3, Major = 6, Minor = 2, Build = 1 });
    pv.Add(new ProductVersions { Version_Id = 4, Major = 7, Minor = 5, Build = 1 });
    pv.Add(new ProductVersions { Version_Id = 5, Major = 10, Minor = 7, Build = 1 });
    pv.Add(new ProductVersions { Version_Id = 6, Major = 11, Minor = 10, Build = 10 });

    int mm = m;
    if (m == 0)
        mm = int.MaxValue;
    int nn = n;
    if (n == 0)
        nn = int.MaxValue;
    int bb = b;
    if (b == 0)
        bb = int.MaxValue;
    var v = pv.FindAll(mj => mj.Major <= m).FindAll(mn => n == 0 ? mn.Major <= mm - 1 && mn.Minor <= nn : mn.Minor <= n).FindAll(bl => b == 0 ? bl.Minor <= nn - 1 && bl.Build <= bb : bl.Build <= b).Last().Version_Id;

    return v;
}

我正在尝试根据主要、次要和构建级别的标准缩小列表,并获取列表的最后一个实体。在这里,我假设列表是根据这些值排序的。

于 2013-09-10T14:13:16.990 回答
-3

我发现这是一种快速简单的方法,但有一些限制。

    var v = from p in pv
            select new { version = p.Version_Id, val = p.Major * 100000000 + p.Minor * 10000 + p.Build };
    int vver=v.ToList().FindAll(pp => pp.val <= m * 100000000 + n * 10000 + b).Last().version;
于 2013-09-10T14:22:06.037 回答