Нахождение количества вхождений строк в определенном формате происходит в данном тексте - PullRequest
3 голосов
/ 25 декабря 2011

У меня есть большая строка, в которой могут быть определенные слова (текст, за которым следует одиночное двоеточие, например «test:»), встречающиеся более одного раза. Например, вот так:

word:
TEST:
word:

TEST:
TEST: // random text

«слово» встречается дважды, а «ТЕСТ» - трижды, но сумма может быть переменной. Кроме того, эти слова не обязательно должны быть в том же порядке, и в той же строке, что и слово, может быть больше текста (как показано в последнем примере «ТЕСТ»). Что мне нужно сделать, это добавить номер вхождения к каждому слову, например, строка вывода должна быть такой:

word_ONE:
TEST_ONE:
word_TWO:

TEST_TWO:
TEST_THREE: // random text

RegEx для получения этих слов, которые я написал, - ^\b[A-Za-z0-9_]{4,}\b:. Однако я не знаю, как быстро выполнить вышеизложенное. Есть идеи?

Ответы [ 4 ]

2 голосов
/ 25 декабря 2011

Regex идеально подходит для этой работы - использование 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);
1 голос
/ 25 декабря 2011

Я думаю, вы можете сделать это с помощью Regax.Replace (строка, строка, 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

1 голос
/ 25 декабря 2011

Если я вас правильно понимаю, регулярное выражение здесь не нужно.

Вы можете разделить вашу большую строку по символу ':'. Может быть, вам также нужно читать построчно (разделить на '\n'). После этого вы просто создаете словарь (IDictionary<string, int>), который подсчитывает вхождения определенных слов. Каждый раз, когда вы находите слово x, вы увеличиваете счетчик в словаре.

EDIT

  1. Читайте ваш файл построчно ИЛИ разбивайте строку на '\n'
  2. Проверьте, присутствует ли ваш разделитель. Либо путем деления на ':' ИЛИ используя регулярное выражение.
  3. Получить первый элемент из массива разбиения ИЛИ первое совпадение с вашим регулярным выражением.
  4. Используйте словарь для подсчета ваших случаев.

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

  5. Если вам нужны слова вместо цифр, создайте для них другой словарь. Так что dictionary[key] равно one, если ключ равен 1. Мэйби, для этого есть другое решение.

0 голосов
/ 25 декабря 2011

Посмотрите на этот пример (я знаю, что он не идеален и не так хорош), давайте оставим точный аргумент для функции 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 "";
}
...