2016-06-08 40 views
0

我有一個表格「GEM」在一個獨特的列數據庫中SPName。 每個記錄的值由一個字符和數字例子查找以前的字符串編號

F12,T16,K15,F10,K14,T9,T7

我想剛纔所選擇的一個之前找到數 例如:

輸入:F12輸出:F10

輸入:T9輸出:T7

輸入:T16輸出:T9

我想消除數字那麼就分貝搜索輸入一個之前每個號碼沒有任何的,但聽起來像這將是糟糕的表現。

Gem gem; 
    for(i= input; i>0; i--) 
    { 
     gem = Uow.Gems.GetAll().FirstOrDefault(x=> RemoveChar(x.SpName) == input) 
     If(gem!=null) break; 
    } 

任何提示?

+2

的最好的事情,如果可能的話,將是你的數據庫改變將字母和數字分隔爲單獨的列。 – juharr

+0

Thx Juharr,但我不能這樣做。 – Maro

+0

在調用性能不佳之前,您是否測試過它?如果沒有,我建議你這樣做。 –

回答

1

醜陋的方式(沒有異常處理等)做你想做什麼:

重要提示:不要忘記,要做到這一點的最好辦法是通過添加一列,以改變你的分貝juharr告訴過你。

List<string> ints = new List<string>(); 
    ints.Add("F12"); 
    ints.Add("T16"); 
    ints.Add("K15"); 
    ints.Add("F10"); 
    ints.Add("K14"); 
    ints.Add("T9"); 
    ints.Add("T7"); 

    var ordered = ints.Select((s, i) => new 
    { 
     nb = int.Parse(s.Substring(1)), 
     text = s.Substring(0, 1), 
     val = s, 
    }).OrderBy(arg => arg.text).ThenBy(arg => arg.nb).ToList(); 

    var index = ordered.FindIndex(arg => arg.val == "T16"); 
    Console.WriteLine(ordered[index - 1].val); 
    Console.ReadLine(); 
+0

爲什麼添加FindIndex作爲擴展類? LINQ提供這種方法。 – Andy

1

我認爲這會返回你以後的值;

public string GetPrevious(string value) 
    { 
     var list = new[] 
     { 
      new {SPName = "F12"}, 
      new {SPName = "T16"}, 
      new {SPName = "K15"}, 
      new {SPName = "F10"}, 
      new {SPName = "K14"}, 
      new {SPName = "T9"}, 
      new {SPName = "T7"} 
     }; 

     return 
      list.Where(
       l => l.SPName.ToCharArray().First() == value.ToCharArray().First() && 
        GetValue(l.SPName) < GetValue(value)).OrderByDescending(l => GetValue(l.SPName)).First().SPName; 
    } 

    public int GetValue(string value) 
    { 
     return int.Parse(value.Substring(1, value.Length - 1)); 
    } 

不幸的是它很難知道有多快,這將有很多值運行,而無需您的原始表數據(我不建議你將它張貼)。

+0

該表有1,431,600條記錄 – Maro

+0

我猜想它會是這樣的,你有沒有嘗試按字符串長度過濾(因爲你的結果永遠不會超過你的輸入?)。在做慢速的工作之前,基本上需要一些有效的方法來減小設置的大小。 –

1

這個怎麼樣,不知道的性能,但應該給你的SQL一個SPName LIKE 'T%@'所以應使用索引:

var input = "T9"; 
var Gem = Uow.Gems.Where 
     (g => g.SPName.StartsWith(input.Substring(0,1)) && 
       Convert.ToInt32(g.SPName.Substring(1)) < 
        Convert.ToInt32(input.Substring(1))) 
    .OrderByDescending(g => Convert.ToInt32(g.SPName.Substring(1))) 
    .Take(1); 

我認爲這應該生成這個SQL:

-- Region Parameters 
DECLARE @p0 VarChar(1000) = 'F%' 
DECLARE @p1 Int = 1 
DECLARE @p2 Int = 12 
DECLARE @p3 Int = 1 
-- EndRegion 
SELECT TOP (1) [t0].[SPName] 
FROM [Gem] AS [t0] 
WHERE ([t0].[SPName] LIKE @p0) AND ((CONVERT(Int,SUBSTRING([t0].[SPName], @p1 + 1, CONVERT(Int,DATALENGTH([t0].[SPName]))))) < @p2) 
ORDER BY CONVERT(Int,SUBSTRING([t0].[SPName], @p3 + 1, CONVERT(Int,DATALENGTH([t0].[SPName])))) DESC 
1

我會建議使用一個簡單的緩存來填充所有的寶石和他們使用比較器的順序。

 // Use your Uow.Gems.GetAll() list of gems 
     string[] gems = new string[] { "F12", "T16", "K15", "F10", "K14", "T9", "T7", "A12", "A11" }; 

     string input = "A12"; 

     //Cache it something like this Uow.Gems.GetAll().OrderBy(x => x, new GemComparer()).ToList() 
     var cacheGems = gems.OrderBy(x => x, new GemComparer()); 

     foreach (var thing in cacheGems) 
     { 
      Console.WriteLine(thing); 
     } 

     var previous = cacheGems.TakeWhile(x => x != input).LastOrDefault(); 

     var next = cacheGems.SkipWhile(x => x != input).Skip(1).FirstOrDefault(); 

     Console.WriteLine(previous); 

     Console.WriteLine(next); 

將是空的,如果沒有找到

A11 A12 F10 F12 K14 K15 T16 T7 T9'

輸出:前面:A11,接下來F10

public class GemComparer : IComparer<string> 
    { 
     public int Compare(string s1, string s2) 
     { 
      if (IsNumeric(s1) && IsNumeric(s2)) 
      { 
       if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1; 
       if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1; 
       if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0; 
      } 

      if (IsNumeric(s1) && !IsNumeric(s2)) 
       return -1; 

      if (!IsNumeric(s1) && IsNumeric(s2)) 
       return 1; 

      return string.Compare(s1, s2, true); 
     } 

     public static bool IsNumeric(object value) 
     { 
      try 
      { 
       int i; 
       return int.TryParse(value.ToString(), out i); 
      } 
      catch (FormatException) 
      { 
       return false; 
      } 
     } 
    }