Преобразование разделенных запятыми строк ints в массив int

Я нашел способ сделать это наоборот: создать строку, разделенную запятыми, из списка или массива int, но не о том, как преобразовать входные данные, такие как string str = "1,2,3,4,5";, в массив или список int.

Вот моя реализация (вдохновленная этим сообщением Эриком Липпертом):

    public static IEnumerable<int> StringToIntList(string str)
    {
        if (String.IsNullOrEmpty(str))
        {
            yield break;
        }

        var chunks = str.Split(',').AsEnumerable();

        using (var rator = chunks.GetEnumerator())
        {
            while (rator.MoveNext())
            {
                int i = 0;

                if (Int32.TryParse(rator.Current, out i))
                {
                    yield return i;
                }
                else
                {
                    continue;
                }
            }
        }
    }

Считаете ли вы, что это хороший подход или есть более простой, возможно, даже встроенный способ?

РЕДАКТИРОВАТЬ: Извините за любую путаницу, но метод должен обрабатывать недопустимый ввод типа "1,2,,,3" или "###, 5," и т.д., пропустив его.

Ответ 1

Вы должны использовать цикл foreach, например:

public static IEnumerable<int> StringToIntList(string str) {
    if (String.IsNullOrEmpty(str))
        yield break;

    foreach(var s in str.Split(',')) {
        int num;
        if (int.TryParse(s, out num))
            yield return num;
    }
}

Обратите внимание, что, как и ваш исходный пост, это игнорирует числа, которые не могут быть проанализированы.

Если вы хотите выбросить исключение, если число не может быть проанализировано, вы можете сделать это гораздо проще с помощью LINQ:

return (str ?? "").Split(',').Select<string, int>(int.Parse);

Ответ 2

Если вы не хотите иметь текущее поведение обработки ошибок, это очень просто:

return text.Split(',').Select(x => int.Parse(x));

В противном случае я бы использовал дополнительный вспомогательный метод (как видно сегодня утром):

public static int? TryParseInt32(string text)
{
    int value;
    return int.TryParse(text, out value) ? value : (int?) null;
}

и

return text.Split(',').Select<string, int?>(TryParseInt32)
                      .Where(x => x.HasValue)
                      .Select(x => x.Value);

или если вы не хотите использовать преобразование группы методов:

return text.Split(',').Select(t => t.TryParseInt32(t)
                      .Where(x => x.HasValue)
                      .Select(x => x.Value);

или в форме выражения запроса:

return from t in text.Split(',')
       select TryParseInt32(t) into x
       where x.HasValue
       select x.Value;

Ответ 3

Без использования лямбда-функции и только для действительных входов я думаю, что это яснее:

Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);

Ответ 4

- ИЗМЕНИТЬ - Похоже, я слишком буквально взял его вопрос, он спрашивал массив ints, а не List --EDIT ENDS -

Еще один вспомогательный метод...

private static int[] StringToIntArray(string myNumbers)
{
    List<int> myIntegers = new List<int>();
    Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
    {
        int currentInt;
        if (Int32.TryParse(s, out currentInt))
            myIntegers.Add(currentInt);
    });
    return myIntegers.ToArray();
}

быстрый тестовый код для него тоже...

static void Main(string[] args)
{
    string myNumbers = "1,2,3,4,5";
    int[] myArray = StringToIntArray(myNumbers);
    Console.WriteLine(myArray.Sum().ToString()); // sum is 15.

    myNumbers = "1,2,3,4,5,6,bad";
    myArray = StringToIntArray(myNumbers);
    Console.WriteLine(myArray.Sum().ToString()); // sum is 21

    Console.ReadLine();
}

Ответ 5

Это было задано раньше..Net имеет встроенную функцию ConvertAll для преобразования между массивом одного типа в массив другого типа. Вы можете комбинировать это с Split для разделения строки на массив строк

Пример функции:

 static int[] ToIntArray(this string value, char separator)
 {
     return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
 }

Взято отсюда

Ответ 6

Это для longs, но вы можете легко его модифицировать для работы с ints.

private static long[] ConvertStringArrayToLongArray(string str)
{
    return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}

Ответ 7

Я не понимаю, почему выключение перечислителя явно дает вам преимущество перед использованием foreach. Также не нужно называть AsEnumerable на chunks.

Ответ 8

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

Ответ 9

Я увлекаюсь простым решением, которое сработало для меня.

String.Join(",",str.Split(','));