Пихните разграниченную строку в Список <интервал>

Если у меня есть, например, следующая строка:

"123; 3344; 4334; 12 дюймов

и я хочу эти числа в дженерике List<int>, Я предполагаю, что не знаю о хорошем пути здесь кроме разделить в цикле и сделать, преобразование затем добавляет к a List<int> посредством каждого повторения. У кого-либо есть другие способы пойти об этом?

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

public List<int> StringToList(string stringToSplit, char splitDelimiter)
{
    List<int> list = new List<int>();

    if (string.IsNullOrEmpty(stringToSplit))
        return list;

    string[] values = stringToSplit.Split(splitDelimiter);

    if (values.Length <= 1)
        return list;

    foreach (string s in values)
    {
        int i;
        if (Int32.TryParse(s, out i))
            list.Add(i);
    }

    return list;
}

Это - новый строковый служебный метод, который я планирую на использовании каждый раз, когда я должен преобразовать разграниченный список строк для Списка

Таким образом, я возвращаю пустой список назад вызывающей стороне, если что-то перестало работать. Хороший/Плохой? действительно ли довольно распространено сделать это?

Да, существуют более "изящные" способы сделать это с LINQ, но я хочу сделать это вручную.. старый путь на данный момент только к моему собственному пониманию.

Кроме того, что беспокоит меня об этом:

list.AddRange(str.Split(';').Select(Int32.Parse));

это, я понятия не имею:

  1. Как проталкиваться TryParse там вместо этого.
  2. Что, если str.Split(';').Select(Int32.Parse) просто сбои по любой причине... затем метод, в котором находится этот AddRange, собирается аварийно завершиться и если я не добавляю попытку/выгоду вокруг этой целой вещи, я завинчен, если я не обрабатываю его правильно.
6
задан Hertzel Guinness 27 July 2011 в 06:05
поделиться

4 ответа

string str = "123;3344;4334;12";
List<int> list = new List<int>();

foreach (string s in str.Split(';'))
{
    list.Add( Int32.Parse(s));
}
5
ответ дан 8 December 2019 в 17:18
поделиться
List<int> list = (from numString in "123;3344;4334;12".Split(';') 
                  select int.Parse(numString)).ToList();
3
ответ дан 8 December 2019 в 17:18
поделиться
static int? ToInt32OrNull(string s)
{
    int value;
    return (Int32.TryParse(s, out value)) ? value : default(int?);      
}
// ...
var str = "123;3344;4334;12"; 
var list = new List<int>();
list.AddRange(str.Split(';')
                 .Select(ToInt32OrNull)
                 .Where(i => i != null)
                 .Cast<int>());

Замечания автора вопроса:

Я не знаю хорошего способа, кроме как разделить в цикле и выполнить преобразование, а затем добавить в список

В общем, это основная причина, по которой LINQ был привнесен в C# - чтобы устранить необходимость работать с последовательностями значений, реализуя циклы, и вместо этого просто объявить о своем намерении преобразовать последовательность. Если вы когда-нибудь подумаете: "Я не знаю, как это сделать, кроме как с помощью цикла" - самое время обратить внимание на конструкцию LINQ, которая сделает всю работу за вас.

Обновление о производительности:

Ниже был задан вопрос о производительности LINQ. Хотя в комментариях отстаивается идея о том, что LINQ медленнее, поскольку мы получаем преимущества читаемости, сопровождаемости и композиции, есть еще один аспект, который дает LINQ легкое преимущество в производительности: параллелизм. Вот пример, где добавление всего одного вызова метода расширения, AsParallel(), удваивает производительность. Это отличный пример того, как масштабирование побеждает микрооптимизацию, даже не требуя тщательных измерений. Заметьте, я не утверждаю, что микрооптимизация никогда не нужна, но с инструментами, доступными нам на этом уровне абстракции, необходимость в ней становится исчезающе малой.

class Program
{
    private const int ElementCount = 10000000;

    static void Main(string[] args)
    {
        var str = generateString();
        var stopwatch = new Stopwatch();

        var list1 = new List<int>(ElementCount); 
        var list2 = new List<int>(ElementCount);

        var split = str.Split(';');

        stopwatch.Start();
        list1.AddRange(split
                          .Select(ToInt32OrNull) 
                          .Where(i => i != null) 
                          .Cast<int>());
        stopwatch.Stop();

        TimeSpan nonParallel = stopwatch.Elapsed;

        stopwatch.Restart();

        list2.AddRange(split
                          .AsParallel()
                          .Select(ToInt32OrNull)
                          .Where(i => i != null)
                          .Cast<int>());

        stopwatch.Stop();

        TimeSpan parallel = stopwatch.Elapsed;

        Debug.WriteLine("Non-parallel: {0}", nonParallel);
        Debug.WriteLine("Parallel: {0}", parallel);
    }

    private static String generateString()
    {
        var builder = new StringBuilder(1048576);
        var rnd = new Random();

        for (int i = 0; i < ElementCount; i++)
        {
            builder.Append(rnd.Next(99999));
            builder.Append(';');
        }

        builder.Length--;

        return builder.ToString();
    }

    static int? ToInt32OrNull(string s)
    {
        int value;
        return (Int32.TryParse(s, out value)) ? value : default(int?);
    } 
}

Непараллельно: 00:00:07.0719911

Параллельно: 00:00:04.5933906

6
ответ дан 8 December 2019 в 17:18
поделиться
string myString = "123;3344;4334;12";
var ints = new List<int>();
(from s in myString.Split(';')
 select int.Parse()).ToList().ForEach(i=>ints.Add(i));

Я слышал, что в .Net 4.0 к ForEach добавили Enumerable, так что ToList там может быть не нужен (не могу проверить).

1
ответ дан 8 December 2019 в 17:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: