Else int.TryParse step block in Lambda syntax

Suppose I have a string array and it can contain some data that can be parsed into integer

.

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

      

I am trying to convert this string array to integer array using LINQ method Select

, something like this: -

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

      

Output:

2,3, 0 , 5,6,8 // Don't want 0 here

Here in the else block int.TryParse

I should have specified the default (0), but I don't need that, so I named my question "By-Pass" with the else part.

Then I used this query and it works fine, means it does not insert unnecessary null if the string is not parsed: -

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();

      

But it seems like a lot of code, just to ignore the default, I design, filter and project again. Is it correct?

+3


source to share


4 answers


I will say that your second example is more than an adequate solution to your problem.

Unlike the other answers, this actually makes it explicit that you only want values ​​that can be parsed. All other decisions, being smart, deceive this fact. The main reason I found a second example of a better solution is the field isParsed

, especially when combined with .Where(x => x.isParsed)

. This is what makes it obvious that you only want values ​​that have been successfully parsed. Anyone who reads the code for the first time will immediately think "just get the values ​​that were parsed". Also, there is no ambiguity in the code.



Also, I would disagree that the second example is bad because it is longer. You should focus more on how to self-describe your code rather than being shorter. This is one of the wrong ideas new developers get. They think they are better than developers if they can generate shorter code, that they are better than developers. While code golf is an interesting discipline, most people don't want to see code like this in production.

+4


source


Why not implement it the old way - at least its easily understandable

        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);
        });

      



You can save some tiger balm !!!

+3


source


You can use SelectMany

:

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

      

+2


source


I think your code looks good and readable. You can consider using a nullable int for the unfortunate parsing result, and then filter it out:

    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();

      

Using a value null

for a null value is the usual, built-in way of representing a missing value. Also, in very tight loops, it avoids memory pressure when allocating an anonymous class.

+1


source







All Articles