在string中搜索多个字符串

时间:2018-01-17 05:23:20

标签: c# string

在给定的字符串中,很容易搜索第一次出现的子字符串,如下所示:

int position = "01234".IndexOf ("23"); // returns 2

我想搜索多个可能字符串中的任何一个的第一个匹配项:

var options = new [] {"77", "34", "12"};
int position = "01234".ImaginaryIndexOf (options); // should return 1

这种功能似乎不存在于.NET框架中。我错过了吗?

编辑:为了澄清,我正在寻找一种适用于大输入和不均匀分布选项的方法。想象一下类似于

的东西
var options = new [] {"x", "y"};
new String ('x', 1000*1000).IndexOf (options)

6 个答案:

答案 0 :(得分:2)

我没有意识到的内置方法..

但是为了做到这一点,您可以迭代所有options并为每个计算IndexOf。然后检索不是-1的最小值("未找到")

int position = options.Select(o => "01234".IndexOf(o))
                      .OrderBy(i =>i).FirstOrDefault(i=> i != -1);

或者代替排序(O(nlogn))找到最小值(O(n)):

int position = options.Select(o => "01234".IndexOf(o))
                      .Where(i => i != -1).DefaultIfEmpty(-1).Min();

至于编辑你可以考虑构建suffix trees的数组 - 数组包含m个项目,其中m是options个单词的不同首字母数量。作为一般例子:

如果选项为:"some", "word", "something", "other"则您构建:

    0        1        2...
 +-----------------------+
 |  s    |   w    |   o  |
 +- | ------ | ------ | -+
    o        o        t
    |        |        |
    m        r        h
    |        |        |
    e        d        e
   / \       |        |
  $   t      r        $
      |      |
      ...    $

然后迭代你的字符串,并为每个字母检查它是否在数组中。如果没有继续下一个。如果是,那么您可以在嵌套树中加深并检查字符串的下一个字母与树中的下一个级别相比较。如果在主字符串末尾未到达任何$,则文本中没有options项。 当然,您可以将数组作为HashSet<T>来改进对单词首字母的搜索。

答案 1 :(得分:2)

也许是这样的;

var options = new[] { "77", "34", "12" };
var position = options.Select(x => "01234".IndexOf(x))
    .Where(x => x > -1).OrderBy(x => x).DefaultIfEmpty(-1)
    .FirstOrDefault();

您可以定义字符串扩展名;

public static class StringExtensions
{
    public static int ImaginaryIndexOf(this string str,IEnumerable<string> options)
    {
        return options.Select(x => str.IndexOf(x))
            .Where(x => x > -1).OrderBy(x => x)
            .DefaultIfEmpty(-1).FirstOrDefault();
    }
}

然后;

var options = new[] { "77", "34", "12" };
"01234".ImaginaryIndexOf(options);

答案 2 :(得分:0)

您好我们可以通过使用for循环或使用正则表达式来解决这个问题。尝试以下代码我用于循环查找第一次出现的字符串的索引。

var options = new[] { "77", "34", "12" };
        for (int i = 0; i < options.Length; i++)
        {
            //MessageBox.Show(options[i].ToString); 
            int p

var options = new[] { "77", "34", "12" };
for (int i = 0; i < options.Length; i++)
{

  int position = "770123473673412".IndexOf(options[i].ToString()); 
  MessageBox.Show(position.ToString());
}

答案 3 :(得分:0)

使用一些LINQ非常简单。棘手的部分是处理-1 ...但是如果你理解了无符号和有符号整数,你就可以通过演员来解决这个问题。

static class StringExtensions
{
    public static int ImaginaryIndexOf(this string input, IEnumerable<string> searchFor)
    {
        return (int)searchFor
            .Select
            (
                s => (uint)input.IndexOf(s) 
            )
            .Min();
    }
}

Try it out on DotNetFiddle

答案 4 :(得分:0)

作为替代解决方案,您可以使用Regex

string input = "01234";
var rgex = new System.Text.RegularExpressions.Regex("(77|34|12)");
var match = rgex.Match(input);
int position = match.Success ? match.Index : -1;

答案 5 :(得分:-2)

您好我们可以通过使用for循环或使用正则表达式来解决这个问题。尝试以下代码我用于循环查找第一次出现的字符串的索引。

var options = new[] { "77", "34", "12" };
for (int i = 0; i < options.Length; i++)
{

  int position = "770123473673412".IndexOf(options[i].ToString()); 
  MessageBox.Show(position.ToString());
}