2010-06-29 1 views
6

Если у меня есть, например, следующая строка:Шов разделителей строки в список <int>

«123; 3344; 4334; 12»

, и я хочу, чтобы эти цифры в общем List<int>, я предполагаю, что я не знаю здесь хорошего способа, кроме как разбить в цикле и сделать преобразование, а затем добавить к 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, взорвется, и если я не добавлю попытку/поймать все это, я ввернусь, если не буду правильно обработайте его.
+0

Использование TryParse здесь является серьезной ошибкой: http://en.wikipedia.org/wiki/GIGO –

ответ

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

foreach (string s in str.Split(';')) 
{ 
    list.Add(Int32.Parse(s)); 
} 
+1

+1, вы прочитали название! Я бы предложил использовать TryParse вместо Parse. – 2010-06-29 01:31:08

+0

Я нашел, если вы можете просто сделать Список list = "123; 3344; 4334; 12" .Split (";"); Я знаю, что вы можете с помощью массива: string [] list = "123; 3344; 4334; 12" .Split (";"); – PositiveGuy

+1

@ coffee, no. Вы не можете неявно преобразовать из массива строк в «Список ». Кроме того, это должно быть 'Split (';')'. Обратите внимание на одну цитату, потому что это символ буква. –

3
List<int> list = (from numString in "123;3344;4334;12".Split(';') 
        select int.Parse(numString)).ToList(); 
6
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, которая будет работать для вас.

Performance Update:

Выполнение LINQ было quesioned ниже. Хотя в комментариях идея 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

Parallel: 00: 00: 04,5933906

+0

Да, я задаюсь вопросом о производительности по сравнению с стандартным расщеплением в цикле, хотя – PositiveGuy

+0

@coffeeaddict: это почти всегда небрежно, и его следует рассматривать только для изменения, если оно измерено и найдено проблема: вот хорошее, недавнее сравнение: http://jerrytech.blogspot.com/2010/02/revisiting-c-loop-performance.html – codekaizen

+0

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

1
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<T>, поэтому ToList может быть ненужным (не может быть проверен).

+0

После 'ToList' вы * имеете * список int. «ForEach» не используется. –

+0

@Matthew Flaschen, согласился. Моя первоначальная (и, по общему признанию, поспешная) первоначальная мысль заключалась в том, что список может быть не оригинальным, и содержимое, возможно, потребуется сохранить. то есть добавьте результаты в существующий список без замены. –

-1

Я думаю, что это самый простой

var str = "123;3344;4334;12"; 
    var list = str.Split(';').ToList().Cast<int>(); 
+0

-1: Это никогда не работает, потому что вы не можете наложить строку на целое число. Вы можете только разобрать его (используя 'int.Parse()' или 'int.TryParse()'). – Oliver

Смежные вопросы