C# 定位 * 在由竖线分隔的字符串中的位置
C# locating where the * is in a string separated by pipes
我必须找到 * 所在的位置,而它可能 none,第一个位置 |第二名 |第三名。
位置用竖线隔开|
于是
否 * 通配符是
`ABC|DEF|GHI`
然而,虽然这可能是 1 种情况,但其他 3 种是
string testPosition1 = "*|DEF|GHI";
string testPosition2 = "ABC|*|GHI";
string testPosition3 = "ABC|DEF|*";
我收集到我应该使用 IndexOf ,但似乎我应该合并 | (管道)知道位置(不仅仅是长度,因为值在 3 个位置中的每一个都可能是长的或短的。所以我只想知道 * 是否在第一、第二或第三位置(或根本不在)
因此我正在这样做,但我不知道它是在第一个管道还是第二个管道之前
if(testPosition1.IndexOf("*") > 0)
{
// Look for pipes?
}
您可以尝试使用 linq 在竖线字符处拆分字符串,然后获取仅包含 *
的元素的索引
var x = testPosition2.Split('|').Select((k, i) => new { text = k, index = i}).FirstOrDefault(p => p.text == "*" );
if(x != null) Console.WriteLine(x.index);
因此,第一行开始在管道处拆分字符串,创建一个字符串数组。该序列被传递给 Select 扩展,该扩展枚举传递字符串文本 (k) 和索引 (i) 的序列。使用这两个参数,我们构建了一系列具有两个属性(文本和索引)的匿名对象。 FirstOrDefault 从此序列中提取文本等于 * 的对象,我们可以打印该对象的 属性 索引。
有很多方法可以解决这个问题。最具可读性的实际上可能只是用困难的方式来做(即扫描字符串以找到第一个 '*'
字符,跟踪您一路上看到的 '|'
个字符)。
也就是说,这可能具有类似的可读性并且更简洁:
int wildcardPosition = Array.IndexOf(testPosition1.Split('|'), "*");
Returns -1
如果未找到,否则 '|'
分隔字符串的段包含通配符字符串的从 0 开始的索引。
这仅在通配符恰好是 one-character 字符串 "*"
时有效。如果您需要支持其他变体,您仍然需要拆分字符串,但是您可以遍历数组以查找您需要的任何条件。
其他答案很好(而且可能更好),但是这里有另一种方法,老式的 for 循环 和 try-get 模式
public bool TryGetStar(string input, out int index)
{
var split = input.Split('|');
for (index = 0; index < split.Length; index++)
if (split[index] == "*")
return true;
return false;
}
或者,如果您正在处理大型 字符串 并试图节省分配。您可以完全删除 Split
并使用单个解析 O(n)
public bool TryGetStar(string input, out int index)
{
index = 0;
for (var i = 0; i < input.Length; i++)
if (input[i] == '|') index++;
else if (input[i] == '*') return true;
return false;
}
注意:如果性能是一个考虑因素,您还可以使用 unsafe
和 指针 或 Span<Char>
,这会提供少量效率。
尝试 DotNETFiddle:
testPosition.IndexOf("*") - testPosition.Replace("|","").IndexOf("*")
找到通配符(“*”)的索引,如果您删除竖线(“|”)字符,看看它移动了多远。结果是 zero-based 索引。
从问题中得到以下代码段:
if(testPosition1.IndexOf("*") > 0)
{
}
如果您现在位于 if
语句中,您确定星号存在。
从那时起,一个有效的解决方案可能是检查前两个字符和最后两个字符。
if (testPosition1.IndexOf("*") > 0)
{
if (testPosition1[0] == '*' && testPosition[1] == '|')
{
// First position.
}
else if (testPosition1[testPosition.Length - 1] == '*' && testPosition1[testPosition.Length - 2] == '|')
{
// Third (last) position.
}
else
{
// Second position.
}
}
这里假设最多只能有一个*
存在,也假设如果有一个*
存在,它只能被管道包围。例如,我假设像 ABC|DEF|G*H
这样的输入是无效的。
如果您想删除此假设,您可以对字符串执行 one-pass 循环并跟踪必要的信息。
我必须找到 * 所在的位置,而它可能 none,第一个位置 |第二名 |第三名。
位置用竖线隔开|
于是
否 * 通配符是
`ABC|DEF|GHI`
然而,虽然这可能是 1 种情况,但其他 3 种是
string testPosition1 = "*|DEF|GHI";
string testPosition2 = "ABC|*|GHI";
string testPosition3 = "ABC|DEF|*";
我收集到我应该使用 IndexOf ,但似乎我应该合并 | (管道)知道位置(不仅仅是长度,因为值在 3 个位置中的每一个都可能是长的或短的。所以我只想知道 * 是否在第一、第二或第三位置(或根本不在)
因此我正在这样做,但我不知道它是在第一个管道还是第二个管道之前
if(testPosition1.IndexOf("*") > 0)
{
// Look for pipes?
}
您可以尝试使用 linq 在竖线字符处拆分字符串,然后获取仅包含 *
的元素的索引var x = testPosition2.Split('|').Select((k, i) => new { text = k, index = i}).FirstOrDefault(p => p.text == "*" );
if(x != null) Console.WriteLine(x.index);
因此,第一行开始在管道处拆分字符串,创建一个字符串数组。该序列被传递给 Select 扩展,该扩展枚举传递字符串文本 (k) 和索引 (i) 的序列。使用这两个参数,我们构建了一系列具有两个属性(文本和索引)的匿名对象。 FirstOrDefault 从此序列中提取文本等于 * 的对象,我们可以打印该对象的 属性 索引。
有很多方法可以解决这个问题。最具可读性的实际上可能只是用困难的方式来做(即扫描字符串以找到第一个 '*'
字符,跟踪您一路上看到的 '|'
个字符)。
也就是说,这可能具有类似的可读性并且更简洁:
int wildcardPosition = Array.IndexOf(testPosition1.Split('|'), "*");
Returns -1
如果未找到,否则 '|'
分隔字符串的段包含通配符字符串的从 0 开始的索引。
这仅在通配符恰好是 one-character 字符串 "*"
时有效。如果您需要支持其他变体,您仍然需要拆分字符串,但是您可以遍历数组以查找您需要的任何条件。
其他答案很好(而且可能更好),但是这里有另一种方法,老式的 for 循环 和 try-get 模式
public bool TryGetStar(string input, out int index)
{
var split = input.Split('|');
for (index = 0; index < split.Length; index++)
if (split[index] == "*")
return true;
return false;
}
或者,如果您正在处理大型 字符串 并试图节省分配。您可以完全删除 Split
并使用单个解析 O(n)
public bool TryGetStar(string input, out int index)
{
index = 0;
for (var i = 0; i < input.Length; i++)
if (input[i] == '|') index++;
else if (input[i] == '*') return true;
return false;
}
注意:如果性能是一个考虑因素,您还可以使用 unsafe
和 指针 或 Span<Char>
,这会提供少量效率。
尝试 DotNETFiddle:
testPosition.IndexOf("*") - testPosition.Replace("|","").IndexOf("*")
找到通配符(“*”)的索引,如果您删除竖线(“|”)字符,看看它移动了多远。结果是 zero-based 索引。
从问题中得到以下代码段:
if(testPosition1.IndexOf("*") > 0)
{
}
如果您现在位于 if
语句中,您确定星号存在。
从那时起,一个有效的解决方案可能是检查前两个字符和最后两个字符。
if (testPosition1.IndexOf("*") > 0)
{
if (testPosition1[0] == '*' && testPosition[1] == '|')
{
// First position.
}
else if (testPosition1[testPosition.Length - 1] == '*' && testPosition1[testPosition.Length - 2] == '|')
{
// Third (last) position.
}
else
{
// Second position.
}
}
这里假设最多只能有一个*
存在,也假设如果有一个*
存在,它只能被管道包围。例如,我假设像 ABC|DEF|G*H
这样的输入是无效的。
如果您想删除此假设,您可以对字符串执行 one-pass 循环并跟踪必要的信息。