2012-02-15 121 views
0

我有一个字符串,可以包含任何内容,但99%的时间是几个英语句子。.Net查找字符串中的所有字偏移量

我需要采取该字符串,并获得代表每个词的开始(或换句话说,在每个空白的结尾处)的索引列表。如果需要空白空间的定义,则至少需要Space,CR,LF和Period。

这样做最简单的方法是什么?我认为有一个比For循环更好的方法 - 我正在考虑使用lambda表达式,但我看不到一种方法来做到这一点不会递归 - 这似乎是乞求堆栈溢出...

示例数据:

Peter Piper picked a peck 
of pickled peppers 

希望的输出是下面的数字。旁边的评论说明:

6, 'Peter ' 
12, 'Peter Piper ' 
19, 'Peter Piper picked ' 
21, 'Peter Piper picked a ' 
26, 'Peter Piper picked a peck[CR]' 
29, 'Peter Piper picked a peck[CR]of ' 
37 'Peter Piper picked a peck[CR]of pickled ' 
+0

我用一个简单的for循环去。你可以使用linq,但在这种情况下会更慢更丑。 – CodesInChaos 2012-02-15 22:56:23

+1

示例数据和所需输出将会有所帮助。 – Alan 2012-02-15 22:56:59

+0

@Alan好点 - 编辑。 – Basic 2012-02-15 23:02:30

回答

2

这里有一种方法,包含一个正则表达式一个lambda。它可能不是最有效的技术,但它是一个不错的,声明的一行:

var indices = Regex.Matches(inputString, @"[^\s\.]+") 
        .Cast<Match>() 
        .Select(match => match.Index) 
        .ToArray(); 
+0

非常优雅 - 我不得不与你分享。 – Basic 2012-02-16 00:03:25

1

对于这种情况,最好是主观。在“哇,我可以使用一行代码”方面可能更好,但由于您需要知道值的索引,因此简单的for循环会很快写入,并且更容易维护。

鉴于它是O(n)性能,应该足够适合您的情况,我会说,只需使用for循环并继续下一个问题即可。

+0

公平点 - 我明显有太多的时间在我的手:) – Basic 2012-02-15 23:11:20

1

下面的函数,你需要什么不for循环。不知道它实际上更短,虽然;)

static List<int> FindWordStarts(string sentence, Func<char, bool> is_separator) { 

    var indexes = new List<int>(); 
    bool separator = true; 

    sentence.Aggregate(
     0, 
     (index, c) => { 
      if (is_separator(c)) 
       separator = true; 
      else if (separator) { 
       indexes.Add(index); 
       separator = false; 
      } 
      return ++index; 
     } 
    ); 

    return indexes; 

} 

使用方法如下:

string sentence = "Peter Piper picked a peck\rof pickled peppers"; 
var indexes = FindWordStarts(sentence, c => Char.IsWhiteSpace(c) || Char.IsPunctuation(c)); 
foreach (int index in indexes) 
    Console.WriteLine(index); 

,其结果是:

0 
6 
12 
19 
21 
26 
29 
37 
+0

+1 - 比整个地方的状态变量for循环更清晰,更具可读性 – Basic 2012-02-16 00:04:51

相关问题