检查字符串是否“大部分”为大写字母的快速方法

Fast way to check if string is `mostly` capital

我正在用 C# 为聊天室编写一个机器人,我想检测一条消息是否包含太多大写字母。如果消息的大写字母总数超过消息总长度的 one-third 并且总长度大于 13,则消息包含太多大写字母。这是为了防止较小的邮件被标记。

现在我正在遍历每个字符并查看它是否为大写。这对于长度合理的消息来说很好。但是,如果您遇到垃圾邮件发送者或巨魔,他们不会总是 post 合理长度的消息。最大字符数限制为 2000,我无法更改。使用我的方法,它开始停滞在 500+ 个字符附近。这给了垃圾邮件发送者足够的时间来粘贴消息并再次发送,有效地淹没了聊天,而机器人却在努力跟上。

我目前拥有的代码:

bool isMostlyUpper = (message.Count(c => char.IsUpper(c)) >= message.Length * 0.3f) && message.Length > 13;

我无法将消息与 string.ToUpper() 进行比较,因为我仍然想检测消息是否主要是大写而不是全部大写。

有没有一种方法可以在不遍历每个字符的情况下做到这一点?或更快获得结果的方法?我可以添加检查以查看消息是否 > 500 但有时会有 500+ 可以通过的长消息。

有没有人有什么巧妙的解决办法?谢谢。

如果在达到条件时跳出 foor 循环,在某些情况下会节省一些时间

int count = 0;
float maxLenght = message.Length * 0.3f;
bool isMostlyUpper = false;

foreach (char c in message)
{
    if (char.IsUpper(c))
    {
        count++;
    }

    if(count >= maxLenght)
    {
        isMostlyUpper = true;
        break;
    }

}

您还可以跟踪最后一条被标记的消息,并将其与收到的新消息进行比较,这样可以阻止人们发送垃圾邮件,并且您不必多次重新计算同一消息。

消息太长时开始跳过字符

private static bool IsMostlyUpper (string message)
{
    if (message.Length > 13) {
        int step = 1 + message.Length / 100; // integer division.
        // 1 for message length < 100
        // 2 for message length < 200
        // 3 for message length < 300

        int limit = message.Length / step / 3;
        int upperCase = 0;
        for (int i = 0; i < message.Length; i += step) {
            if (Char.IsUpper(message[i])) {
                upperCase++;
                if (upperCase >= limit) {
                    return true;
                }
            }
        }
    }
    return false;
}

使用更大的除数来测试更多的字符。


如果您认为非常聪明的机器人可以欺骗您的算法,您还可以创建一个随机除数

private static Random _random = new Random(); // static field

创建除数

int divisor = _random.Next(150, 200);
int step = 1 + message.Length / divisor;

但这只是节省几微秒的复杂性!