在字符串中查找上一个数字

时间:2016-06-08 11:14:25

标签: c# linq

我有一张桌子" GEM"在具有唯一列 SPName 的数据库中。 每个记录的值由一个char和数字示例

组成
  

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;
    }

任何提示?

4 个答案:

答案 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();

答案 1 :(得分: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));
    }

不幸的是,很难知道在没有原始表数据的情况下,这将与多个值一起运行的速度有多快(我不建议你发布它)。

答案 2 :(得分: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

答案 3 :(得分:1)

我建议使用一个简单的缓存来填充所有宝石并使用comparer对它们进行排序。

        //  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;
            }
        }
    }