【问题标题】:Finding the number of occurences strings in a specific format occur in a given text查找特定格式的字符串在给定文本中出现的次数
【发布时间】:2011-12-25 15:29:33
【问题描述】:

我有一个大字符串,其中可能有多次出现的特定单词(文本后跟一个冒号,例如“test:”)。例如,像这样:

word:
TEST:
word:

TEST:
TEST: // random text

“word”出现两次,“TEST”出现三次,但数量可以变化。此外,这些单词的顺序不必相同,并且可以在与单词相同的行中有更多文本(如“TEST”的最后一个示例所示)。我需要做的是将出现次数附加到每个单词,例如输出字符串需要是这样的:

word_ONE:
TEST_ONE:
word_TWO:

TEST_TWO:
TEST_THREE: // random text

获取我写的这些单词的正则表达式是^\b[A-Za-z0-9_]{4,}\b:。但是,我不知道如何快速完成上述操作。有什么想法吗?

【问题讨论】:

  • 它们总是按顺序出现吗?在第一个 word: 之后会有一个 TEST: 吗?
  • 它们不必按顺序排列。
  • 您能否阐明该示例以包含当您在行中有其他文本和多个特殊单词时的情况(假设允许)?

标签: c# .net regex string .net-2.0


【解决方案1】:

正则表达式非常适合这项工作 - 将 Replace 与匹配评估器一起使用:

这个例子没有经过测试也没有编译:

public class Fix
{
    public static String Execute(string largeText)
    {
        return Regex.Replace(largeText, "^(\w{4,}):", new Fix().Evaluator);
    }

    private Dictionary<String, int> counters = new Dictionary<String, int>();
    private static String[] numbers = {"ONE", "TWO", "THREE",...};
    public String Evaluator(Match m)
    {
        String word = m.Groups[1].Value;
        int count;
        if (!counters.TryGetValue(word, out count))
          count = 0;
        count++;
        counters[word] = count;

        return word + "_" + numbers[count-1] + ":";
    }
}

这应该会返回您在调用时请求的内容:

result = Fix.Execute(largeText);

【讨论】:

  • return word + "_" + numbers[count-1] + ":";
  • 其实,无视上面的评论。我修复了您的代码的一些问题(改为字符串 word = m.Value),它现在似乎可以工作了。谢谢。
【解决方案2】:

我认为您可以使用 Regax.Replace(string, string, MatchEvaluator) 和字典来做到这一点。

Dictionary<string, int> wordCount=new Dictionary<string,int>();
string AppendIndex(Match m)
{
   string matchedString = m.ToString();
   if(wordCount.Contains(matchedString))
     wordCount[matchedString]=wordCount[matchedString]+1;
   else
     wordCount.Add(matchedString, 1);
  return matchedString + "_"+ wordCount.ToString();// in the format: word_1, word_2
}


string inputText = "....";
string regexText = @"";

   static void Main() 
   {
      string text = "....";
      string result = Regex.Replace(text, @"^\b[A-Za-z0-9_]{4,}\b:",
         new MatchEvaluator(AppendIndex));
   }

看到这个: http://msdn.microsoft.com/en-US/library/cft8645c(v=VS.80).aspx

【讨论】:

  • 哦,我明白了。不过有个小问题,函数调用时返回的是垃圾而不是数字,而且出现在冒号之后而不是之前。
  • 嗯,您的“return matchingString + "_"+ wordCount.ToString();// 格式似乎有问题:word_1, word_2”。它应该是 wordCount[matchedString].ToString(),但除此之外它似乎还在工作。
【解决方案3】:

如果我理解正确,这里不需要正则表达式。

您可以用':' 字符分割大字符串。也许您还需要逐行阅读(由'\n' 拆分)。之后,您只需创建一个字典 (IDictionary&lt;string, int&gt;),它会计算某些单词的出现次数。每次找到单词 x 时,都会增加字典中的计数器。

编辑

  1. 逐行读取文件或将字符串按'\n'拆分

  2. 检查您的分隔符是否存在。通过':' 拆分或使用正则表达式。

  3. 从拆分数组中获取第一项或您的正则表达式的第一个匹配项。

  4. 使用字典来计算出现次数。

    if (dictionary.Contains(key)) dictionary[key]++;
    else dictionary.Add(key, 1);

  5. 如果您需要单词而不是数字,请为这些创建另一个字典。所以dictionary[key]等于one如果key等于1。 Mabye 有另一种解决方案。

【讨论】:

  • 我应该使用正则表达式,因为 a) 这些词只出现在大字符串中一行的开头(因此 ^ 在正则表达式中)b) 这些词是整个词和 c) 它们长度为 3 个或更多字母。另外,我将如何编辑字符串以添加“_ONE”、“_TWO”或任何数字?
  • @david:这更多是不使用正则表达式的原因,因为格式是如此固定(以: 结尾的文本——只需使用字符串索引)。这可以完全按照@MatthiasKoch 所说的那样完成。如果您希望它快速,请不要在不必要时使用正则表达式。
  • @bobbymcr:我主要担心的是它们是完整的单词,可以是任何大小写,据我所知,字符串函数不处理这些。
  • 如果你有string line代表这条线,你需要做的就是检查!string.IsNullOrEmpty(line)然后line[line.Length - 1] == ':'。现在你知道line.Substring(0, line.Length - 1) 一定是你的话。
  • 我忘了说除了单词,还可以有其他的文字在行。 :s
【解决方案4】:

看看这个例子(我知道它不是完美的,也不是很好) 让我们为 Split 函数留下确切的参数,我认为它会有所帮助

static void Main(string[] args)
{
  string a = "word:word:test:-1+234=567:test:test:";
  string[] tks = a.Split(':');
  Regex re = new Regex(@"^\b[A-Za-z0-9_]{4,}\b");
  var res = from x in tks
  where re.Matches(x).Count > 0
  select x + DecodeNO(tks.Count(y=>y.Equals(x)));
  foreach (var item in res)
  {
    Console.WriteLine(item);
  }
  Console.ReadLine();
}

private static string DecodeNO(int n)
{
 switch (n)
 {
   case 1:
     return "_one";
   case 2:
     return "_two";
   case 3:
     return "_three";
  }
 return "";
}

【讨论】:

  • 认为这非常需要维护。
  • 您使用的是 Linq,我在帖子中提到我使用的是 NET 2.0,所以这对我不起作用(如果您想知道为什么我仍然坚持使用 NET 2.0,那是因为以后我必须将我的应用程序移植到 Linux,但这不是重点)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
  • 2010-09-22
  • 2023-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多