2016-06-08 42 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; 
      } 
     } 
    }