Get string from array or set default value in a one liner

Get string from array or set default value in a one liner

So we have ?? to parse its right-hand value for when the left hand is null. 
What is the equivalent for a string[].
For example
string value = "One - Two"
string firstValue = value.Split('-')[0] ?? string.Empty;
string secondValue = value.Split('-')[1] ?? string.Empty;

Above example would still crash if we would try to get a third index or if string value = "One". Because it is not null but IndexOutOfRangeException is thrown.
So what is a one-line solution to tackle the above problem? I'd like to avoid the try-catch scenario because this gives ugly code. 
I want to get value out of a string[] with a string.Empty as a backup value so my string is never null. 


Answer 1:

Well, you can try Linq:

using System.Linq;


string thirdValue = value.Split('-').ElementAtOrDefault(2) ?? string.Empty;

However, your code has a drawback: you constantly Split the same string. I suggest extracting value.Split('-'):

string value = "One - Two"
var items = value.Split('-');

string firstValue = items.ElementAtOrDefault(0) ?? string.Empty;
string secondValue = items.ElementAtOrDefault(1) ?? string.Empty;

Answer 2:

I suggest you create a method for this. which will accept two inputs of type string(representing the input string) and an integer(represents the specified index), and should return the split value if the specified index is available, else it will return an empty string:

string GetSubstring(string input, int index)
    string returnValue = String.Empty;
    string[] substrings = input.Split(new[] { "-" }, StringSplitOptions.RemoveEmptyEntries);
    returnValue = substrings.Length > index ? substrings[index] : returnValue;
    return returnValue;

Here is a working example for your reference

Answer 3:

One way to achieve this is to use MoreLinq‘s Lead and tuple destructuring:

string value = "One - Two";
var (first, second) = value.Split('-').Lead(1, string.Empty, (x, y) => (x, y)).First();

Or, if you want a more generic approach that works for all indices:

string value = "One - Two - Three - Fourth - Fifth";
var (first, second) = value.Split('-').Skip(6).Concat(string.Empty).Lead(7, string.Empty, (x, y) => (x, y)).First();

This code will get the seventh and fourteenth entries (neither of which are there, so string.Empty will be used for both).

Another option to consider is to assign two different variables on the same line of code:

string value = "One - Two";
var split = value.Split('-');
string first = split[0] ?? string.Empty, second = split.ElementAtOrDefault(1) ?? string.Empty;

This gives you three lines of code, good performance and reasonable level of clarity and readability.

Note there is no need to use ElementOrDefault(0) – better to use [0] since Split will never return an array with no elements in it.

Another option would be to use destructuring – but that is really only useful if you are interested in contiguous entries at the start of the array (although it could be tweaked to take index parameters reasonably simply):

public static void Destructure<T>(this T[] items, T defaultValue, out T t0, out T t1)
    t0 = items.Length > 0 ? items[0] : defaultValue;
    t1 = items.Length > 1 ? items[1] : defaultValue;

Answer 4:

Maybe the following code will be useful

string value = "One - Two";
string firstValue = (value.Split('-').Length == 1 ? value.Split('-')[0] : null) ?? string.Empty;
string secondValue = (value.Split('-').Length == 2 ? value.Split('-')[1] : null) ?? string.Empty;