从字符串中提取整数

10
假设我有一个网页,目前通过url参数接受单个ID值:
http://example.com/mypage.aspx?ID=1234

我想改为接受ID列表,如下所示:
http://example.com/mypage.aspx?IDs=1234,4321,6789

因此,它可通过字符串 context.Request.QueryString["IDs"] 在我的代码中使用。将该字符串值转换为 List<int> 的最佳方法是什么?

编辑:我知道如何在逗号上使用 .split() 获取字符串列表,但我询问的原因是我不知道如何轻松地将该字符串列表转换为 int 列表。这仍然是 .Net 2.0,因此没有 lambda 表达式。

13个回答

13

无意冒犯那些提供清晰答案的人,但许多人似乎在回答你的问题而不是解决你的问题。你想要多个ID,所以你认为可以这样做:

http://example.com/mypage.aspx?IDs=1234,4321,6789

问题是这是一个不够强大的解决方案。将来,如果您想要多个值,如果它们有逗号,该怎么办?更好的解决方案(并且这在查询字符串中完全有效)是使用同一名称的多个参数:

http://example.com/mypage.aspx?ID=1234;ID=4321;ID=6789

然后,无论您使用什么查询字符串解析器,它都应该能够返回ID列表。如果它不能处理这个(并且还能处理分号而不是和号),那么它就是有问题的。


1
asp.net在处理“page.aspx?id=1,2,3,4&otherid=4,5,6,7”时没有任何问题,因此我无法理解为什么逗号分隔列表是一种不稳健的解决方案。 - Robert Paulson
1
因为,正如所述,如果允许包含逗号,则在逗号上拆分会有问题。CGI协议允许使用相同名称的多个参数,因此整个“我是否可以在逗号上拆分”问题变得无关紧要。这就是重复参数名称的作用。 - Ovid
我认为如果列出字母数字ID或GUID,ID内部不会出现逗号,从这个角度来看,逗号是一个强大的解决方案。但我想可能还有其他问题,例如维基语法解析器认为链接在逗号处结束? - KajMagnus
1
这是一个可怕的想法!如果将来的值包含“;”,该怎么办? “;”不比“,”更好-如果您想要准确无误,两者都被RFC禁止。 - Nas Banov
1
@Nas:抱歉,但那不正确。在字符串中,如果分号(;)不是用作分隔符,则需要对其进行URI转义(在这种情况下为%3B),因为它是保留字符。请参见RFC 2396第2.2节-http://www.ietf.org/rfc/rfc2396.txt。任何不能处理此内容的查询字符串解析器都是错误的。您是正确的,逗号(,)也是一个保留字符,必须进行转义,但您无法确定它是否被转义以分隔或因为它是有效值。 - Ovid
这是一个非常优雅且信息量丰富的解决方案。我不知道它可以像这样完成。 - Richard C

12

可能会有类似这样的解决方案:

public static IList<int> GetIdListFromString(string idList)
{
    string[] values = idList.Split(',');

    List<int> ids = new List<int>(values.Length);

    foreach (string s in values)
    {
        int i;

        if (int.TryParse(s, out i))
        {
            ids.Add(i);
        }
    }

    return ids;
}

那么它将被使用:

string intString = "1234,4321,6789";

IList<int> list = GetIdListFromString(intString);

foreach (int i in list)
{
    Console.WriteLine(i);
}

很好,我正准备发布完全相同的答案 :( - Huppie

4
您可以从数组实例化一个List<T>。
VB.NET:
Dim lstIDs as new List(of Integer)(ids.split(','))

但是,如果数组包含非整数元素,则容易出现转换错误


这个问题在于只要有一个转换错误就会导致整个列表出错,但我仍然点了赞,也许这就是我应该追求的行为。 - Joel Coehoorn

2

如果你喜欢函数式风格,可以尝试类似这样的代码:

    string ids = "1,2,3,4,5";

    List<int> l = new List<int>(Array.ConvertAll(
        ids.Split(','), new Converter<string, int>(int.Parse)));

没有Lambda表达式,但您可以使用转换器、谓词和其他可从方法中创建的好东西。

2
我看到我的答案来得比较晚,也就是说其他几个人已经写了相同的答案。因此,我提供了一种使用正则表达式验证和分割字符串的替代方法。
class Program
{
    //Accepts one or more groups of one or more digits, separated by commas.
    private static readonly Regex CSStringPattern = new Regex(@"^(\d+,?)*\d+$");

    //A single ID inside the string. Must only be used after validation
    private static readonly Regex SingleIdPattern = new Regex(@"\d+");

    static void Main(string[] args)
    {
        string queryString = "1234,4321,6789";

        int[] ids = ConvertCommaSeparatedStringToIntArray(queryString);
    }

    private static int[] ConvertCommaSeparatedStringToIntArray(string csString)
    {
        if (!CSStringPattern.IsMatch(csString))
            throw new FormatException(string.Format("Invalid comma separated string '{0}'",
                                                    csString));

        List<int> ids = new List<int>();
        foreach (Match match in SingleIdPattern.Matches(csString))
        {
            ids.Add(int.Parse(match.Value)); //No need to TryParse since string has been validated
        }
        return ids.ToArray();
    }
}

2
我能想到的只有循环遍历字符串列表(从拆分中获取),并对它们逐个执行像 int.TryParse() 这样的操作,然后将它们放入一个新的 List<int> 中。在某个地方将其封装成一个好用的小助手方法,这样就不会太可怕了。

1

split 是首先想到的,但它返回的是一个数组而不是 List;你可以尝试类似这样的代码:


List<int> intList = new List<int>;

foreach (string tempString in ids.split(',')
{
    intList.add (convert.int32(tempString));
}


1

最终代码片段,希望它能从所有建议中选出最好的部分:

Function GetIDs(ByVal IDList As String) As List(Of Integer)
    Dim SplitIDs() As String = IDList.Split(new Char() {","c}, StringSplitOptions.RemoveEmptyEntries)
    GetIDs = new List(Of Integer)(SplitIDs.Length)
    Dim CurID As Integer
    For Each id As String In SplitIDs
        If Integer.TryParse(id, CurID) Then GetIDs.Add(CurID)
    Next id
End Function

我希望能够在一两行内完成代码的内联操作。一行用于创建字符串数组,希望能够找到一些框架中我不知道的东西来处理将其导入到可以智能转换的List<int>中。但如果必须将其移动到方法中,那么我就会这样做。是的,我正在使用VB。我只是更喜欢用C#来提问,因为它们会得到更多的关注,而且我几乎同样熟练。


0

一旦从URL中提取出值,您可以使用string.Split()来拆分这些值。

string[] splitIds = ids.split(',');

0
List<int> convertIDs = new List<int>;
string[] splitIds = ids.split(',');
foreach(string s in splitIds)
{
    convertIDs.Add(int.Parse(s));
}

为了完整性,您会想在for循环(或int.Parse()调用周围)周围放置try/catch,并根据您的要求处理错误。您也可以像这样进行tryparse():

List<int> convertIDs = new List<int>;
string[] splitIds = ids.split(',');
foreach(string s in splitIds)
{
    int i;
    int.TryParse(out i);
    if (i != 0)
       convertIDs.Add(i);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接