2015-08-25 131 views
0

如何編寫一個算法,可以將未使用的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

回答

1

這應該爲你工作:

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

-1

這裏是一個解決方案,我想會的工作:

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'。不工作 –

0

試試這個

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

這是不行的。在這裏,我不想使用數據庫的身份自動增量,它不合邏輯。 –

相關問題