是否可以使用LINQ来检测重复的相邻字符?

时间:2016-06-23 17:50:30

标签: c# linq

我想验证字符串在相邻位置是否包含任何重复字符(来自一组坏字符)。此主题的先前堆栈溢出答案似乎主要是一般形式:

for(int i = 0; i < testString.Length-1; i++){
    if(testString[i] == testString[i+1] && testString[i] == badChar){
        //Handle rejection here
    }
}

是否可以在LINQ中进行此类验证/验证?更一般地说:在LINQ中是否可以将字符串中每个字符的值与

中的下一个字符进行比较

testString.Any(c => /*test goes here*/)致电?

3 个答案:

答案 0 :(得分:5)

您可以使用moreLINQ库中的Pairwise

if(testString.Pairwise((n, m) => new {n, m}).Any(x => x.n == x.m && x.n == badChar))
    // do something

如果您想使用纯LINQ,可以使用Skip / Zip组合破解它:

if(testString.Zip(testString.Skip(1), (n, m) => new {n, m})).Any(x => x.n == x.m && x.n == badChar))
    // do something

但这两种解决方案都比for基于循环的解决方案慢得多,所以我建议不要这样做。

答案 1 :(得分:4)

任何时候你有一个具有Count(或等效)属性和索引器的类,你可以使用Enumerable.Range作为LINQ查询的基础,并在类似于非LINQ代码的索引访问中执行:

bool test = Enumerable.Range(0, testString.Length - 1).Any(i = > 
        testString[i] == testString[i + 1] && testString[i] == badChar)

答案 2 :(得分:3)

如何严重滥用聚合函数?我想这个答案更像是一个不做的例子,即使它是可能的。一段时间和string.indexOf可能是最适合这个问题的。

var items = "ab^cdeef##gg";
var badChars = new[] {'^', '#', '~'};
var doesAdjacentDupeExist = false;
var meaninglessAggregate = items.Aggregate((last, current) => 
    {
        if (last == current && badChars.Contains(last))
        {
            doesAdjacentDupeExist = true;
        };
        return current;
    });

这不是很聪明,但确实有效。它交换查询中的外部变量的设置(坏),依赖于index和elementAt(不是很好)。

var items = "abcdefffghhijjk";
var badChars = new[] { 'f', 'h' };
var indexCieling = items.Count() - 1;
var badCharIndexes = items.Select((item, index) => 
    {
        if (index >= indexCieling)
        {
            return null as int?;
        }
        else
        {
            if (item == items.ElementAt(index + 1) && badChars.Contains(item))
            {
                return index as int?;
            }
            else
            {
                return null as int?;
            }
        }
    });
var doesAdjacentDupeExist = badCharIndexes.Any(x => x.HasValue);