【问题标题】:Get string from array or set default value in a one liner从数组中获取字符串或在一行中设置默认值
【发布时间】:2019-07-30 11:28:53
【问题描述】:

所以我们有?? 来解析它的右手值,当左手为空时。 string[] 的等价物是什么。

例如

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

如果我们尝试获取第三个索引或string value = "One",上述示例仍然会崩溃。因为它不是 null 而是抛出了IndexOutOfRangeException

https://docs.microsoft.com/en-us/dotnet/api/system.indexoutofrangeexception

那么解决上述问题的单线解决方案是什么?我想避免 try-catch 场景,因为这会给出丑陋的代码。

我想从string[] 中获取价值,并将string.Empty 作为备用值,因此我的string 永远不会是null

【问题讨论】:

  • 字符串 secondValue = value.Split('-').Length > 1 ? value.Split('-')[1] ?? string.Empty : string.Empty;
  • string thirdValue = value.Split('-').ElementAtOrDefault(3) ?? "";
  • 你可以使用?: operator,但问题是——你真的在这里用一个班轮获得很多吗?最好将拆分结果保存到局部变量中。您可以构建一个扩展方法,如果参数超出范围而不是使用索引器,它将为数组返回 ""

标签: c# arrays string indexoutofrangeexception


【解决方案1】:

嗯,你可以试试Linq

using System.Linq;

...

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

然而,你的代码有一个缺点:你经常Split相同的字符串。我建议提取value.Split('-')

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

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

【讨论】:

  • 该死,写的是同样的答案 :) 这需要一个using System.Linq; 在顶部。
【解决方案2】:

我建议您为此创建一个方法。它将接受两个字符串类型的输入(表示输入字符串)和一个整数(表示指定的索引),如果指定的索引可用,则返回拆分值,否则返回空字符串:

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

这是一个working example 供您参考

【讨论】:

  • 这可行,但它假设 OP 想要删除空条目。这由他来决定。
  • 谢谢,但 Dmitry 方法效果更好,因为这已经“烘焙”到 C# 中,我不必添加方法
【解决方案3】:

实现此目的的一种方法是使用MoreLinqLead 和元组解构:

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

或者,如果您想要一种适用于所有索引的更通用的方法:

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

此代码将获取第七个和第十四个条目(两者都不存在,因此string.Empty 将用于两者)。

另一个需要考虑的选择是在同一行代码中分配两个不同的变量

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

这为您提供了三行代码、良好的性能以及合理的清晰度和可读性。

注意没有必要使用ElementOrDefault(0) - 最好使用[0],因为Split永远返回一个没有元素的数组。

另一种选择是使用destructuring - 但这仅在您对数组开头的连续条目感兴趣时才有用(尽管可以对其进行调整以合理地简单地采用索引参数):

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

【讨论】:

    【解决方案4】:

    也许下面的代码会有用

    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;
    

    【讨论】:

    • 效率很低。
    • 更短一点的实现是secondValue = value.Split('-').Length &gt;= 2 ? value.Split('-')[1] : string.Empty;(我们可以去掉null..??片段)
    • 应该是&gt;= ,而不是== 比较:Length &gt;= 1Length &gt;= 2
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多