2014-07-09 2 views
0

입력 문자열을 구문 분석 반환 값을 사용하여. 이 코드를 개선하고 싶습니다. 어떻게 구현할 수 있습니까?가장 좋은 방법은 용어를 사전에

using System; 
using System.Collections.Generic; 
using System.Text.RegularExpressions; 

namespace TermsTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string[] tags = { "TAG1", "TAG2", "TAG3", "TAG4", "TAG5", "TAG6", "TAG7", "TAG8" }; 
      string file = "TAG2jjfjfjndbfdjTAG1qqqqqqqTAG3uytygh fhdjdfTAG5hgjdhfghTAG6trgfmxc hdfhdTAG2jfksksdhjskTAG3kdjbjvbsjTAG2jskjdjdvjvbxjkvbjdTAG2jkxcndjcjbkjn"; 

      string tag = "(" + string.Join("|", tags) + ")"; 

      var dictionary = new Dictionary<string, List<string>>(tags.Length); 
      Regex.Replace(file, string.Format(@"({0})(.+?)(?={0}|$)", tag), match => 
                      { 
                       string key = match.Groups[1].Value, value = match.Groups[3].Value; 
                       if (dictionary.ContainsKey(key)) 
                        dictionary[key].Add(value); 
                       else 
                        dictionary[key] = new List<string> {value}; 
                       return ""; 
                      }); 
      foreach (var pair in dictionary) 
      { 
       Console.Write(pair.Key + " =\t"); 
       foreach (var entry in pair.Value) 
       { 
        Console.Write(entry + " "); 
       } 
       Console.WriteLine(); 
       Console.WriteLine(); 
      } 
     } 
    } 
} 

답변

3
string input = "TAG1xxxTAG2yyyTAG3zzzTAG1tttTAG1bbb"; 
var lookup = Regex.Matches(input, @"(TAG\d)(.+?)(?=TAG|$)") 
        .Cast<Match>() 
        .ToLookup(m => m.Groups[1].Value, m => m.Groups[2].Value); 

foreach (var kv in lookup) 
{ 
    Console.WriteLine(kv.Key + " => " + String.Join(", ", kv)); 
} 

출력 :

TAG1 => xxx, ttt, bbb 
TAG2 => yyy 
TAG3 => zzz 
+0

고마워, 훨씬 좋아 보인다! –

0

이 같은 캡처 그룹을 여러 번 재사용 할 수있는 .NET CaptureCollection 객체 고유의 .NET 기능에 대한 완벽한 일이다.

사용이 정규식과을 MatchCollection를 만들 Matches를 사용

(?:TAG1(.*?(?=TAG|$)))?(?:TAG2(.*?(?=TAG|$)))?(?:TAG3(.*?(?=TAG|$)))? 

그런 다음 캡처를 검사 :

  • Groups[1].Captures 모든 TAG1이 포함됩니다
  • Groups[2].Captures 모든 TAG2 포함됩니다
  • Groups[3].Captures에는 모든 TAG3

여기에서 귀하의 최종 데이터 구조에 대한 짧은 단계가 있습니다. 이것이 어떻게 작동하는지, Capture Groups that can be Quantified를 참조에 대한 자세한 내용은

(?>(?:TAG1(.*?(?=TAG|$)))?)(?>(?:TAG2(.*?(?=TAG|$)))?)(?>(?:TAG3(.*?(?=TAG|$)))?) 

:

당신은 원자 토큰을 만들 수 역 추적 가능성을 줄일 수 있습니다.

+0

그것은 전, 100 개 태그, 매우 느린 것 같다. 아니면 내가 틀렸어? –

+0

자, 그룹을 원자 적으로 만들어 역 추적의 가능성을 줄이자 :'(?> (? : TAG1 (? = TAG | $)))?) (?> (?: TAG2 TAG3 (. *? (? = TAG | $)))?)' – zx81

0

GroupBy 방법을 사용하는 당신은 단순히 동일한 태그의 값으로 그룹화되어 일을하려고하는, 그래서 쉽게해야한다 무엇 :

string input = "TAG1xxxTAG2yyyTAG3zzzTAG1tttTAG1bbb"; 
var list = Regex.Matches(input, @"(TAG\d+)(.+?)(?=TAG\d+|$)") 
       .Cast<Match>() 
       .GroupBy(m => m.Groups[1].Value, 
         (key, values) => string.Format("{0} = {{{1}}}", 
              key, 
              string.Join(", ", 
               values.Select(v => v.Groups[2])))); 
var output = string.Join(", ", list); 

을 이 문자열은 output 문자열로 생성됩니다. "TAG1 = {xxx, ttt, bbb}, TAG2 = {yyy}, TAG3 = {zzz}"

0

저는 n입니다. 이 문제에 대한 모든 가정과 관례를 알고 있음을 확신합니다. 그러나 이것은 나에게 비슷한 결과 주었다

var tagColl = string.Join("|", tags); 
var tagGroup = string.Format("(?<tag>{0})(?<val>[a-z]*)", tagColl); 

var result = from x in Regex.Matches(file, tagGroup).Cast<Match>() 
       where x.Success 
       let pair = new { fst = x.Groups["tag"].Value, snd = x.Groups["val"].Value } 
       group pair by pair.fst into g 
       select g; 

을 그리고 간단한 테스트는 다음과 같습니다

Console.WriteLine(string.Join("\r\n", from g in result 
             let coll = string.Join(", ", from item in g select item.snd) 
             select string.Format("{0}: {{{1}}}", g.Key, coll)));