Выделите целые из строки - PullRequest
10 голосов
/ 15 сентября 2008

Допустим, у меня есть веб-страница, которая в настоящее время принимает одно значение идентификатора через параметр URL:
http://example.com/mypage.aspx?ID=1234

Я хочу изменить его, чтобы он принимал список идентификаторов, например:
http://example.com/mypage.aspx?IDs=1234,4321,6789

Так что он доступен для моего кода в виде строки через context.Request.QueryString ["IDs"]. Какой лучший способ превратить это строковое значение в список ?

Редактировать: Я знаю, как сделать .split () на запятую, чтобы получить список строк, но я спрашиваю, потому что я не знаю, как легко преобразовать этот список строк в список int , Это все еще в .Net 2.0, так что лямбды нет.

Ответы [ 13 ]

13 голосов
/ 15 сентября 2008

Не обижайте тех, кто дал четкие ответы, но многие, похоже, отвечают на ваш вопрос, а не решают вашу проблему. Вам нужно несколько идентификаторов, поэтому вы думаете, что могли бы это так:

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

Проблема в том, что это ненадежное решение. В будущем, если вам нужны несколько значений, что вы будете делать, если у них запятые? Лучшее решение (и это совершенно справедливо в строке запроса) - использовать несколько параметров с одинаковым именем:

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

Тогда любой используемый парсер строки запроса должен иметь возможность возвращать список идентификаторов. Если он не может справиться с этим (а также обрабатывает точки с запятой вместо амперсандов), то он сломан.

11 голосов
/ 15 сентября 2008

Примерно так может работать:

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);
}
4 голосов
/ 15 сентября 2008

Вы можете создать экземпляр List из массива.

VB.NET:

Dim lstIDs as new List(of Integer)(ids.split(','))

Это может привести к ошибкам приведения, хотя, если массив содержит элементы не-int

2 голосов
/ 15 сентября 2008

Понятно мой ответ пришел довольно поздно, то есть несколько других написали тоже самое. Поэтому я представляю альтернативный метод, использующий регулярные выражения для проверки и разделения строки.

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 голосов
/ 15 сентября 2008

Если вам нравится функциональный стиль, вы можете попробовать что-то вроде

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

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

Никаких лямбд, но у вас есть конвертеры и предикаты и другие полезные вещи, которые можно сделать из методов.

2 голосов
/ 15 сентября 2008

Все, что я могу придумать, это циклически перебирать список строк (который вы получили при выполнении разбиения) и делать что-то вроде int.TryParse() над ними один за другим и помещать их в новый List<int>. Инкапсулируйте это каким-нибудь милым вспомогательным методом, и это не будет слишком ужасным.

1 голос
/ 15 сентября 2008

Финальный фрагмент кода, который берет то, что, я надеюсь, является лучшим из всех предложений:

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 , который мог бы интеллектуально обрабатывать приведение. Но если я должен переместить это в метод, тогда я буду. И да, я использую VB. Я просто предпочитаю C # для того, чтобы задавать вопросы, потому что они получат большую аудиторию, и я почти так же свободно.

1 голос
/ 15 сентября 2008

split - это первое, что приходит на ум, но возвращает массив, а не список; Вы можете попробовать что-то вроде:


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

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

0 голосов
/ 15 сентября 2008

Я думаю, что самый простой способ - это разделить, как показано выше, а затем перебрать значения и попытаться преобразовать их в int.

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

        int[] ids = ConvertCommaSeparatedStringToIntArray(queryString);
    }

    private static int[] ConvertCommaSeparatedStringToIntArray(string csString)
    {
        //splitting string to substrings
        string[] idStrings = csString.Split(',');

        //initializing int-array of same length
        int[] ids = new int[idStrings.Length];

        //looping all substrings
        for (int i = 0; i < idStrings.Length; i++)
        {
            string idString = idStrings[i];

            //trying to convert one substring to int
            int id;
            if (!int.TryParse(idString, out id))
                throw new FormatException(String.Format("Query string contained malformed id '{0}'", idString));

            //writing value back to the int-array
            ids[i] = id;
        }

        return ids;
    }
}
0 голосов
/ 15 сентября 2008

Для продолжения предыдущего ответа достаточно просто выполнить итерацию по массиву, возвращенному Split, и преобразовать его в новый массив целых чисел. Этот образец ниже в C #:

        string[] splitIds = stringIds.Split(',');

        int[] ids = new int[splitIds.Length];
        for (int i = 0; i < ids.Length; i++) {
            ids[i] = Int32.Parse(splitIds[i]);
        }
...