Int.Parse(String.Split())返回"输入字符串格式不正确"错误

时间:2015-03-06 12:53:07

标签: c# linq

我正在尝试对数组执行LINQ查询,以根据用户的查询过滤掉结果。我在从单个字符串解析两个int时遇到问题。

在我的数据库中,TimeLevels以[mintime]-[maxtime] minutes格式存储为字符串,例如0-5 Minutes。我的用户有一个滑块,可以选择最小和最大时间范围,并将其存储为int数组,其中包含两个值。我正在尝试将[mintime]与第一个值进行比较,将[maxtime]与第二个值进行比较,以查找符合用户时间范围的数据库条目。

这是来自控制器的C#代码,它应该执行过滤:

RefinedResults = InitialResults.Where(
                x => int.Parse(x.TimeLevel.Split('-')[0]) >= data.TimeRange[0] &&
                int.Parse(x.TimeLevel.Split('-')[1]) <= data.TimeRange[1] &&).ToArray();

我的想法是,它首先将0-5 Minutes字符串拆分为-,从而产生两个字符串,05 Minutes,然后解析这些字符串的整数,从而得到仅在05

但是一旦到达Int.Parse,它就会在标题中抛出错误。

4 个答案:

答案 0 :(得分:1)

  

某些x.TimeLevel数据库记录存储为"30-40+ Minutes"。有没有方法只是提取int

您可以使用正则表达式来匹配字符串的整数部分,如下所示:

RefinedResults = InitialResults
    .Where(x => {
        var m = Regex.Match(x, @"^(\d+)-(\d+)");
        return m.Success
            && int.Parse(m.Groups[1]) >= data.TimeRange[0]
            && int.Parse(m.Groups[2]) <= data.TimeRange[1];
    }).ToArray();

此方法要求字符串以一对短划线分隔的十进制数开头。它会在第二个数字后忽略任何内容,确保只将数字序列传递给int.Parse

答案 1 :(得分:1)

你的代码不起作用的原因是因为string.Split(“ - ”,“0-5 Minutes”)将返回[0] =“0”和[1] =“5 Minutes”,后者不能作为int解析。

您可以使用正则表达式“\ d +”来分割数字组并忽略非数字。这应该有效:

var refinedResults = 
(
    from result in InitialResults
    let numbers = Regex.Matches(result.TimeLevel, @"\d+")
    where ((int.Parse(numbers[0].Value) >= data.TimeRange[0]) && (int.Parse(numbers[1].Value) <= data.TimeRange[1]))
    select result
).ToArray();

这是一个完整的可编辑控制台应用程序,它演示了它的工作原理。我使用虚拟类来表示你的实际类。

using System;
using System.Linq;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    public class SampleTime
    {
        public SampleTime(string timeLevel)
        {
            TimeLevel = timeLevel;
        }

        public readonly string TimeLevel;
    }

    public class Data
    {
        public int[] TimeRange = new int[2];
    }

    class Program
    {
        private static void Main(string[] args)
        {
            var initialResults = new []
            {
                new SampleTime("0-5 Minutes"),
                new SampleTime("4-5 Minutes"), // Should be selected below.
                new SampleTime("1-8 Minutes"),
                new SampleTime("4-6 Minutes"), // Should be selected below.
                new SampleTime("4-7 Minutes"),
                new SampleTime("5-6 Minutes"), // Should be selected below.
                new SampleTime("20-30 Minutes")
            };

            // Find all ranges between 4 and 6 inclusive.

            Data data = new Data();
            data.TimeRange[0] = 4;
            data.TimeRange[1] = 6;

            // The output of this should be (as commented in the array initialisation above):
            //
            // 4-5 Minutes
            // 4-6 Minutes
            // 5-6 Minutes

            // Here's the significant code:

            var refinedResults = 
            (
                from result in initialResults
                let numbers = Regex.Matches(result.TimeLevel, @"\d+")
                where ((int.Parse(numbers[0].Value) >= data.TimeRange[0]) && (int.Parse(numbers[1].Value) <= data.TimeRange[1]))
                select result
            ).ToArray();

            foreach (var result in refinedResults)
            {
                Console.WriteLine(result.TimeLevel);
            }
        }
    }
}

答案 2 :(得分:0)

问题是你要按-分割,而不是minutes部分的分隔符空格分割。因此,您可以使用Split(' ', '-')代替:

InitialResults
    .Where(x => int.Parse(x.TimeLevel.Split('-')[0]) >= data.TimeRange[0] 
             && int.Parse(x.TimeLevel.Split(' ','-')[1]) <= data.TimeRange[1])
    .ToArray();

另外,不要在数据库的一列中存储三个信息。这只是令人讨厌的错误和糟糕表现的根源。在数据库中过滤也是比较困难的,这应该是首选方式或维护数据库一致性。


关于您的评论,格式可以是0-40+ Minutes。然后你可以使用......

InitialResults
    .Select(x => new { 
        TimeLevel = x.TimeLevel, 
        MinMaxPart = x.TimeLevel.Split(' ')[0]
    })
    .Select(x => new { 
        TimeLevel = x.TimeLevel, 
        Min = int.Parse(x.MinMaxPart.Split('-')[0].Trim('+')),
        Max = int.Parse(x.MinMaxPart.Split('-')[1].Trim('+'))
    })
    .Where(x => x.Min >= data.TimeRange[0] && x.Max <= data.TimeRange[1])
    .Select(x => x.TimeLevel)
    .ToArray();

答案 3 :(得分:0)

错误发生是因为&#34;分钟&#34;字符串的一部分。 你可以截断&#34;分钟&#34;分裂之前的部分,如; x.TimeLevel.Remove(x.IndexOf(&#34;&#34;)) 然后就可以拆分了。