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 循环并跟踪必要的信息。