7

这里有另一个棘手的家伙,基本上我想检查一个字符串是否包含单词“Foo”,如果它确实包含它,它是否以它开头?如果它确实以 Foo 开头,它应该是唯一以大写字母开头的 Foo,所有其他都应该是小写字母。

如果满足上述条件,则应返回 true。

如果字符串包含 Foo 但不以 Foo 开头,它应该立即返回 false,因为字符串中间不能有大写的 Foo。

如果所述字符串包含 foo,但不以 Foo 开头,则 foo 的所有实例都应为小写。如果满足此条件,则返回 true。

我应该提到我正在寻找 C# 代码,我尝试过但尚未成功,但由于我只编程了 2 周,我认为这对你们中的一些赛季专业人士来说不会有麻烦。


这是我按照要求尝试过的,我认为它很糟糕,但至少我试过了。

            if (Title.Contains("Foo") == true && Regex.IsMatch(Title, "^Foo") == true)
        {
            CheckAnd = true;
        }
        else if (Title.Contains("Foo") == true && Regex.IsMatch(Title, "^Foo") == false)
        {
            CheckAnd = false;
        }
        else if (Regex.IsMatch(Title, "^foo"))
        {
            CheckAnd = false;
        }
        else
        {
            CheckAnd = true;
        }

好的,伙计们,快到了,这就是我从你所有的答案中得到的:

if (Title.IndexOf("Foo") == 0 && Title.LastIndexOf("Foo") == 0)
        {
            CheckAnd = true;
        }
        else if (Title.LastIndexOf("Foo") > 0)
        {
            CheckAnd = false;
        }
        else if(Title.Contains("foo") && Title.StartsWith("Foo") == false && PUT CHECK HERE)

我需要检查最后一个 else if 语句中所有出现的 foo 是否都是小写的最后一件事?

4

5 回答 5

17

不想看我的书?这是答案:

作为奖励,这是执行速度最快的解决方案。

public void CheckValidFoo(String Title) {     
    return (Title.LastIndexOf("Foo") <= 0);
}

继续阅读编码逻辑课程(幽默这位老人)

这个问题可能很老了,但是为了那些后来发现这个问题的人对如何从逻辑上提炼单词问题感到好奇,这是我对这个极其简单的家庭作业的大量过度分析:

我进行了一组测试,看看哪些选项最快——这通常可以帮助我发现我的逻辑缺陷。我还将解释我的思维过程,因为,恕我直言,了解如何将问题提炼到其核心逻辑对于现实世界的使用来说是一件好事。

毕竟,这就是业务需求文档......需要提炼成功能规范(例如架构设计)的文字问题。

第1步

消除无关信息
根据给定的要求,小写的 foo 可能重要也可能不重要: 没有明确声明不包含 foo 且不包含 Foo 的字符串应返回 false;也没有明确的声明说一个不包含 Foo 和不包含 foo 的字符串应该返回 true。

在一个完美的世界里,你会回去澄清需求,但在某些情况下,没有时间。假设有一个截止日期,我会继续假设我们只关心 Foo 仅在句子的第一个位置是大写,在所有其他时间都是小写,所以我们将完全忽略 foo,如果 "客户”抱怨,指出缺失的清晰度并解释您做出判断的原因(以保持项目按时完成,并在预算内,如果适用)。

第2步

将逻辑分解为 OR/AND 部分:
将 Foo 分解为组件可以让我们查看单个部分,这比查看整体更容易。因此,如果我们将字符串分解为“Foo 之前的内容”(即使那是“无”)和“Foo 之后的内容”,或者如果 Foo 不存在来分解字符串,我们只有一个可以查看。(我们的大脑一直在这样做——这被称为模式识别)。

IF由于未找到 Foo 无法拆分字符串,
    或者
      在 Foo 上拆分给我们的结果不超过两部分:之前什么都没有,
       AND之后的所有内容(由前面的检查暗示只找到一个空的“之前”并且只有一个“节”在"after")        Foo 在字符串的其他任何地方都找不到

听起来不错?嗯,它是 100% 准确的,但我们可以减少一些垃圾并进一步提炼它——请记住,计算机不像人类那样思考,所以我们的心理处理对它们来说效率低下。

因为根本没有找到 Foo 被认为是有效的,并且开头的 Foo 是有效的,但是字符串后面的任何其他地方的 Foo 都是无效的,我们可以说:

IF Foo is not found
    OR
      Foo 在字符串中第一个位置之后的任何位置都找不到

看起来很紧,对吧?现在不要停下来。我们可以做得更好。

如果在一开始就找到了 Foo,我们可以接受它,对吧?所以“Foo is not Found”或“Foo is found in the beginning AND Foo is not found else else”可以从更纯粹的逻辑(布尔、真/假、黑白)的角度来看:

  • LET FNA = "在任何地方都找不到 Foo"
  • LET FN1 = "在位置 1 找不到 Foo"
  • LET FN2 = "在位置 1 之后找不到 Foo"
  • LET FF1 = "Foo 位于位置 1"
  • LET FF2 = "在位置 1 之后找到 Foo"

因此,现在仅将那些保证无效的情况定义为无效,并将其余情况标记为有效。我们将使用布尔数学来确定所有用例。

  • 让 FNA = 有效
  • 让 FN1 = 有效
  • 让 FN2 = 有效
  • LET FF1 = 有效
  • LET FF2 = 无效

现在我们只标记了绝对强制返回 false 的情况,我们可以进行数学运算以查看我们得到无效/false 值的唯一情况。

FNA = FN1 和 FN2(所以如果 FNA & X = true,则 F1 & X 必须为 true,F2 & X 也必须为 true);

FNA 和/或 FF1 = true,所以我们知道这 4 个变量和/或的所有组合 = true;这只剩下一个变量可以组合,我们可以很快看到FF2和任何东西都将永远是错误的。

所以翻译回人类逻辑......看看这个任务有多简单?

只有在位置 1 之后找到 Foo 时才为FALSE

或者,翻转布尔值(因为要求对有效情况返回 true):

如果在位置 1 之后没有找到 Foo,则字符串有效。

或者,说得更像计算机的思维:

如果从字符串末尾扫描到第 2 个到最后一个字符没有找到 Foo,则字符串有效

在那里,现在我们不能再进一步提炼它了。所以让我们对这些不同的逻辑位进行编码,看看它们在实际代码中的表现:

using System;

public static class Test
{
public static bool CheckFooTestA(String SearchMe, String[] FindMe)
{
    //split the string like the human eye does and check the count of Foos 
    //and the position of the Foo or Foos to determine our logic:
    string[] v = SearchMe.Split(FindMe, StringSplitOptions.None);
    
         //Foo not found, OR foo found once and was at the beginning of the string
    return (v.Length == 0 || v.Length == 1 && v[0] == String.Empty);
}
public static bool CheckFooTestB(String SearchMe, String[] FindMe)
{
    //scan the way computers or non-speed readers do, and look for the first instance of Foo
    int i = SearchMe.IndexOf(FindMe[0]);

    //Foo not found OR 
    //    foo found at the start of the string 
    //    AND the last Foo found is also at the start of the string
    return (i == -1 || i == 0 && SearchMe.LastIndexOf(FindMe[0]) == 0 );
}
public static bool CheckFooTestC(String SearchMe, String[] FindMe)
{
    //Use the logic we distilled from the word problem to make this single check:
    return (SearchMe.LastIndexOf(FindMe[0]) <= 0);
}
public static void Main()
{
    String[] x = new String[]{
        "Foo foo Foo bar",
        "Foo foo foo bar",
        "foo foo Foo bar",
        "foo foo foo bar",
        "asfda asdfa asf" };
        
    var s = new []{"Foo"};
    var i = 0;
    bool f=false;
    long End = DateTime.Now.Ticks;
    long Start = DateTime.Now.Ticks;
    for (; i < 1000; i++) {
        f = CheckFooTestA(x[i%5],s);
    }
    End = DateTime.Now.Ticks;
    Console.WriteLine((End - Start).ToString() + " ticks (Test A)");

    i = 0;
    f = false;
    End = DateTime.Now.Ticks;
    Start = DateTime.Now.Ticks;
    for (; i < 1000; i++) {
        f = CheckFooTestB(x[i%5],s);
    }
    End = DateTime.Now.Ticks;
    Console.WriteLine((End - Start).ToString() + " ticks (Test B)");
    
    i = 0;
    f = false;
    End = DateTime.Now.Ticks;
    Start = DateTime.Now.Ticks;
    for (; i < 1000; i++) {
        f = CheckFooTestC(x[i%5],s);
    }
    End = DateTime.Now.Ticks;
    Console.WriteLine((End - Start).ToString() + " ticks (Test C)");
}
}
Test.Main();

输出:

260510 ticks (Test A)
117150 ticks (Test B)
76160 ticks (Test C)

结果和结论

测试 A(对找到的单词进行视觉拆分/计数的人类逻辑)与测试 B(使用带有提炼逻辑的索引进行扫描)相比,测试 A 的运行时间延长了 220% 以上!

测试 C 是表现最好的——只需要对字符串进行一次扫描。所需处理时间不到 30%(测试 A 占用了测试 C 完成相同工作所需时间的 340%!)。

所以希望某个地方的某个学生已经读过这篇文章并且灯泡继续亮着。您总是可以想出一些方法来制作“有效”的东西,但是理解布尔逻辑以及如何将概念提炼到其核心可能会对您的工作质量产生重大影响。

于 2013-11-08T22:36:48.837 回答
6

如果我正确地理解它,这应该做到!

    if (testString.IndexOf("Foo") == 0 && testString.LastIndexOf("Foo") == 0)
        // "Foo foo foo"
        return true;
    else if (testString.IndexOf("Foo") == 0 && testString.LastIndexOf("Foo") > 0)
        // "Foo foo Foo"
        return false;
    else if (testString.Contains("foo")  && testString.IndexOf("Foo") > 0)
        // "foo Foo foo" or "foo foo Foo"
        return false; 
    else if (testString.Contains("foo") && !testString.Contains("Foo"))
        // "foo foo foo"
        return true;  
于 2012-06-19T18:57:09.883 回答
2

这将返回true(因为它包含单词 Foo),然后false(因为 Foo 不在句子的开头)。

        string word = "I am a string i contain Foo, aint that nice?";
        bool conts = word.Contains("Foo");
        int pos = word.IndexOf("Foo");                 
        if (conts)
        {
            if (pos != 0)
            {
                // do something
            }

        }
于 2012-06-19T18:58:09.350 回答
1

请参考 String.IndexOf 方法:

http://msdn.microsoft.com/en-us/library/k8b1470s.aspx

搜索区分大小写,因此只需查找大写单词(例如:“Foo”)。如果 IndexOf 返回 0,则该单词位于第一个位置。

编辑:这就是我会做的事情(在看到你的代码之后)

//changed to check for lowercase foo
if ((Title.StartsWith("Foo") && Title.LastIndexOf("Foo") == 0) 
|| (Title.Contains("foo") && !Title.StartsWith("foo")))
{
    CheckAnd = true;
}
else
    CheckAnd = false;
于 2012-06-19T19:05:16.443 回答
1

如果我正确理解了这个问题,这个方法应该可以工作。

    public bool ContainsFoo(string s)
    {
        bool result = true;

        if (s.IndexOf("Foo") > 0)
        {
            result = false;
        }
        else if (s.LastIndexOf("Foo") > 0)
        {
            result = false;
        }
        return result;
    }

如果我误解了什么,请告诉我。

于 2012-06-19T19:19:44.450 回答