如何编写通过在序列中丢失项目来生成ID的函数?

如何编写通过在序列中丢失项目来生成ID的函数?

问题描述:

如何编写一个算法,可以将未使用的ID从格式为“C00”的1到99开始的序列中取出?例如NewId(['C01', 'C02', 'C03'])应该发出'C04',但NewId(['C02', 'C03', 'C04'])应该发出C01,而NewId(['C01', 'C03', 'C04'])应该产生C02。如何编写通过在序列中丢失项目来生成ID的函数?

我写了一个实现,但结果是错误的。

示例:CAT_ID:C01,C02,C05,C06,C11。当我运行它时,预期的结果是C03。我的算法如下:

  1. 排序ID ASC
  2. 遍历每个项目在列表中
  3. 比较第一值与未来,如果他们是不一样的,加1并退出循环。

这是我的代码:

public static string Get_AreaID_Auto() 
{ 
    string result = ""; 
    if (db.TESTs.ToList().Count <= 0) 
    { 
     result = "01"; 
    } 
    else 
    { 
     int maxId = 0; 
     foreach (var item in db.TESTs.OrderBy(e => e.CAT_ID).ToList()) 
     { 
      if (int.Parse(item.CAT_ID.Substring(1)) + 1 != int.Parse(item.CAT_ID.Substring(1))) 
      { 
       maxId = int.Parse(item.CAT_ID.Substring(1) + 1); 
       break; 
      } 
     } 
     switch (maxId.ToString().Length) 
     { 
      case 1: 
       if (maxId == 9) 
       { 
        result = "10"; 
       } 
       else 
        result = "0" + (maxId + 1); 
       break; 
      case 2: 
       result = "" + (maxId + 1); 
       break; 
      default: 
       break; 
     } 
    } 
    return "C" + result; 
} 

有人能说出什么是错的?

+0

为什么不使用的数据库'自动Increment'功能并保存自己的数据库中大量的心脏疼 – 3dd

+0

自动递增的不是逻辑。例如:你有1,2,3,4,5。如果你删除2,3,那么Id将会是6,而不是逻辑。 –

+0

你是什么意思不是逻辑,如果那些被删除,你想要新的id是2 2,3如果删除 – 3dd

这应该为你工作:

public static string Get_AreaID_Auto() 
{ 
    var existing = db.TESTs.Select(e => e.CAT_ID).OrderBy(x => x).ToList(); 
    if (existing.Count == 0) 
    { 
     return "C01"; 
    } 
    else 
    { 
     return 
      existing 
       .Concat(new [] { "" }) 
       .Select((x, n) => new 
       { 
        actual = x, 
        expected = String.Format("C{0:00}", n + 1), 
       }) 
       .Where(x => x.actual != x.expected) 
       .Select(x => x.expected) 
       .First(); 
    } 
} 

这使用生成和测试方法。不需要解析。

我刚刚实现了.Concat(new [] { "" })的更改,现在不再需要if语句。你可以这样做,而不是:

public static string Get_AreaID_Auto() 
{ 
    return 
     db.TESTs 
      .Select(e => e.CAT_ID) 
      .OrderBy(x => x) 
      .ToArray() 
      .Concat(new [] { "" }) 
      .Select((x, n) => new 
      { 
       actual = x, 
       expected = String.Format("C{0:00}", n + 1), 
      }) 
      .Where(x => x.actual != x.expected) 
      .Select(x => x.expected) 
      .First(); 
} 
+0

好吧,你是对的,它的工作,没有解析。当我使用GeirGrusom代码时,我想念LINQ to Entities无法识别方法'Int32 Parse(System.String)'方法,并且这种方法不能被转换成商店表达式' –

+0

嗨enigmativity,在这里,你忘记了'09',接下来是'10',它错误'Sequence contains no elements', –

+0

@BrianCrist - 我修正了它。问题是两个序列完全相同时失败了。我用'.Concat(new [] {“”})'修复了这个问题。 – Enigmativity

这里是一个解决方案,我想会的工作:

var items = db.TESTs.Select(x => int.Parse(x.CAT_ID.Substring(1))).OrderBy(v => v).ToArray(); 

if(!items.Any()) 
    return "C01"; 

int current = 0; 
for (int i = 0; i < items.Length; i++) 
{ 
    if (items[i] > current + 1) 
      return "C" + (current + 1) .ToString("00"); 
    current = items[i]; 
} 

return "C" + (items.Max() + 1).ToString("00"); 
+0

没问题,请仔细阅读问题,然后给我一些建议code.thank家伙 –

+0

改变到应该希望工作的东西。 – GeirGrusom

+0

尝试3个案例:'1,2,3,5,6 => 4; 2,3,4,5,6 => 1; 1,2,3,4,5 => 6'。不工作 –

试试这个

public static string Get_AreaID_Auto() 
{ 
    string result = ""; 
    if (db.TESTs.ToList().Count <= 0) 
    { 
     result = "01"; 
    } 
    else 
    { 
    var item = db.TESTs.OrderByDescending(e => e.CAT_ID).First(); 
    result = int.Parse(item.CAT_ID.Substring(1)) + 1;  
    } 
    return string.Format("C{0:D3}",result); 
} 

更新的代码......现在试试这个

public static string Get_AreaID_Auto() 
{ 
    string result = ""; 
    if (db.TESTs.ToList().Count <= 0) 
    { 
     result = "01"; 
    } 
    else 
    { 
var items = db.TESTs.OrderBy(e => e.CAT_ID).ToArray(); 
for(int i=0;i<items.count;i++) 
{ 
    if ((i==items.count-1) || (int.Parse(items[i].CAT_ID.Substring(1)) + 1 != int.Parse(items[i+1].CAT_ID.Substring(1)))) 
      { 
       result = int.Parse(items[i].CAT_ID.Substring(1) + 1); 
       break; 
      } 
}  
    } 
    return string.Format("C{0:D2}",result); 
} 
+0

那么,更好的方法是使用数据库自​​动增量功能,但假设你正在尝试在代码中这样做的原因。 – Viru

+0

这是不行的。在这里,我不想使用数据库的身份自动增量,它不合逻辑。 –