2014-12-31 2 views
3

Предположим, у меня есть строковый массив, и он может содержать некоторые данные, которые могут быть проанализированы в integer.Блок байпаса else int.TryParse в Lambda Синтаксис

string[] strnums = { "2", "3", "hello", "5", "6", "8" }; 

Я пытаюсь преобразовать этот массив строк в целочисленный массив с помощью LINQ Select метод, что-то вроде этого: -

int[] numbers = strnums.Select(x => 
       { 
        int temp = 0; 
        return int.TryParse(x, out temp) ? temp : 0; 
       }).ToArray(); 

Output: 2,3, , 5,6,8 // Не хочу 0 здесь

Здесь, в блоке else int.TryParse, мне пришлось указать значение по умолчанию (0), но мне это не нужно, поэтому я назвал свой вопрос «By-Pass» «Другая часть.

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

int[] numbers1 = strnums.Select(x => 
       { 
        int temp = 0; 
        bool isParsed = int.TryParse(x, out temp); 
        return new { temp, isParsed }; 
       }) 
       .Where(x => x.isParsed) 
       .Select(x => x.temp) 
       .ToArray(); 

Но это, кажется, много кода, просто для того, чтобы не учитывать значение по умолчанию, я проектирую, фильтрую и снова проектирую. Правильно ли это?

+0

Я думаю, что это имеет смысл вообще, так как Linq рассматривает между проецированием и фильтрацией как отдельные последовательные операции.Я склонен использовать для этого значение nullable int, но ваш пробег может отличаться. – dbc

+2

Я не вижу проблем со вторым примером. Это имеет смысл и на самом деле явно описывает то, что вы хотите, вместо того, чтобы быть «умным». – Euphoric

ответ

4

скажу, что ваш второй пример более чем адекватное решение вашей проблемы.

В отличие от других ответов, это фактически делает его явным, что вам нужны только значения, которые можно разобрать. Все остальные решения, будучи умными, обманывают этот факт. Основная причина, по которой я нашел второй пример лучшего решения, - это поле isParsed, особенно в сочетании с .Where(x => x.isParsed). Вот что делает очевидным, что вам нужны только те значения, которые были успешно проанализированы. Любой, кто впервые прочитает код, сразу подумает «только получить значения, которые были разобраны». Кроме того, в коде нет двусмысленности.

Кроме того, я бы не согласился с тем, что второй пример плох, потому что он длиннее. Вы должны больше сосредоточиться на том, как самоописывать код, а не короче. Это одна из неправильных идей, которые получают новые разработчики. Они думают, что они лучше разработчиков, если они могут генерировать код короче, что они лучше разработчиков. И хотя кодекс-гольф - интересная дисциплина, большинство людей не хотят видеть такой код в производственной среде.

+0

Er ... Два других ответа (которые не были удалены, во всяком случае), Ли и dbc, оба кажутся мне понятными о намерении кода. Что вы не понимаете в них? – hvd

+0

@hvd Но они не совсем поняли о намерениях программиста. dbc'd почти такой же, как в вопросе, и Ли понадобится минута, пытаясь понять, что происходит, не зная проблему заранее. – Euphoric

+0

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

1

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

int[] numbers = strnums.Select(x => 
    { 
     int temp = 0; 
     return int.TryParse(x, out temp) ? (int?)temp : (int?)null; 
    }) 
    .Where(i => i != null) 
    .Select(i => i.Value) 
    .ToArray(); 

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

+1

Это то, что я хотел бы сделать, за исключением того, что я мог бы выделить селектор в функцию многократного использования. Фактически это тот же подход, что и вопрос: 'Nullable ' - это почти анонимный класс вопроса, с 'isParsed' переименованный в' HasValue' и 'temp', переименованный в' Value'. – hvd

+0

@hvd - правда, я думаю, что подход в вопросе хорош. Но для итерации над чем-то очень маленьким, как целое число, это позволяет избежать давления памяти при распределении анонимного типа для каждой итерации. Я был укушен этим раньше, поэтому я стараюсь избегать этого. – dbc

+1

Несомненно, что в целом будет незначительным, но может сделать измеримую разницу в плотных петлях. Но, как я уже сказал, это то, что я буду делать, я не говорю, что вы должны изменить эту часть. :) Лично, если встроенный тип удовлетворяет моим потребностям так же, как и пользовательский тип, этого достаточно для того, чтобы я пошел на встроенный тип. Читаемость может быть причиной того, что встроенный тип может быть худшим, но «null» хорошо известен как значение для представления «у нас нет никакого значения« int », так что это выглядит хорошо для меня. – hvd

2

Вы можете использовать SelectMany:

int[] ints = strnums.SelectMany(s => 
      { 
       int i; 
       return int.TryParse(s, out i) ? new[] { i } : new int[0]; 
      }).ToArray(); 
3

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

 var nums = new List<int>(); 
     var numStrings = new List<string>{ "1", "2", "hello" }; 
     numStrings.ForEach(numString => 
     { 
      int temp; 
      if (int.TryParse(numString, out temp)) 
       nums.Add(temp); 
     }); 

Вы можете сэкономить тигр бальзам !!!

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