2009-10-18 4 views
1

매칭 패턴에 정규식을 사용하고 있습니다. 다음 예제의 예제에서 매칭 문자열과 모음을 매칭합니다.Linq 패턴 매칭

void VowelsCountInEachWord() 
{ 
    Regex rx = new Regex("[aeiou]"); 
    var words=new string[] 
         {"aesthetic", "benevolent", "abstract", 
          "capricious", "complacent", "conciliatory", 
          "devious", "diligent", "discernible","dogmatic", 
          "eccentric","fallacious","indifferent","inquisitive", 
          "meticulous","pertinent","plausible", "reticent" 
         }; 

    var filter = from w in words where (rx.IsMatch(w.ToLower())) select new 

       {w,count=VowelsCounting(w)}; 


foreach (var v in filter) 
{ 
    Console.WriteLine("String {0} contains {1} vowels", v.w, v.count); 
} 

} 

public int VowelsCounting(string value) 
{ 

    int cnt=0; 
    foreach (char c in value) 
    { 
     switch (c) 
     { 
       case 'a':cnt++;break; 
       case 'e':cnt++;break; 
       case 'i':cnt++;break; 
       case 'o':cnt++;break; 
       case 'u':cnt++;break; 
      } 
    } 
      return cnt++; 
    } 

1) 정규 표현식을 사용하지 않으면 C#은 패턴 매칭을 위해 어떤 구성을 제공합니까?

2) 문자열에 대해 개별 문자를 계산하려면 내 고유 한 방법을 파생해야합니까?

+0

답변을 얻길 바랍니다. 질문에'regex' 태그를 추가하십시오. – HuBeZa

답변

3

1)?

모든 것을 한 번에 제공하는 정규식만큼 강력한 것은 없습니다.

2) 내가 내 자신의 방법을 도출해야 할 문자열에 대한 개별 문자 계산을 위해?

나는이 방법을하지 않는 것이 좋습니다,하지만 난 그냥 당신이 그것을 달성하는 방법에 내장 일부를 사용할 수 있다는 것을 보여주기 위해 주장하고있다. String.IndexOf을 사용하고 0 인덱스에서 시작하여 "a"를 찾고 양수의 일치 항목에서 카운터를 증가시키면서 루프를 따라 계속 질주 할 수 있습니다. 그런 다음 "e"... "u"를 반복하지만 정규 표현식이나 for 루프보다 훨씬 효율적이지 않습니다.

더 나은 방법은 문자열 char을 char로 반복하고 기존 switch 문에 입력하거나 일부 모음에서 찾으십시오.

LINQ를 사용하려는 경우 위의 루프 아이디어를 적합하도록 다시 작성하는 방법은 다음과 같습니다. 이 아이디어는 HuBeZa's solution과 유사하므로 +1하십시오. 그러나, 나는 모양 업에 대한 목록을 사용하는 경우 무시하도록 StringComparison.InvariantCultureIgnoreCase 열거를 사용

var vowels = new List<string> { "a", "e", "i", "o", "u" }; 
var query = words.Select(s => new 
      { 
       Text = s, 
       Count = s.Count(c => vowels.Exists(vowel => 
        vowel.Equals(c.ToString(), 
         StringComparison.InvariantCultureIgnoreCase))) 
      }); 
foreach (var item in query) 
{ 
    Console.WriteLine("String {0} contains {1} vowels", item.Text, item.Count); 
} 

내 원래 정규식 응답은 다음과 같습니다.


정규식 접근

사용하고있는 것보다 더 나은 정규식 솔루션이있다. 나는 당신이 그것을 알고 있는지 확신 할 수 없기 때문에 나는 그것이 게시물을 보증한다고 느꼈다. 질문 # 1에서 "정규 표현식을 사용하지 않고"라고 말했지만 IMHO는 자신의 방법을 파생시켜야하는지 묻는 질문 # 2와 직접 충돌합니다.

당신은 Regex.Matches method 및 반환을 MatchCollection에 Count property 사용하여 코드를 단축 할 수

:

1) 문자열 : BTW

Regex rx = new Regex("[aeiou]"); 
// to ignore case use: new Regex("[aeiou]", RegexOptions.IgnoreCase); 
string[] words = 
{ 
    "aesthetic", "benevolent", "abstract", 
    "capricious", "complacent", "conciliatory", 
    "devious", "diligent", "discernible","dogmatic", 
    "eccentric","fallacious","indifferent","inquisitive", 
    "meticulous","pertinent","plausible", "reticent" 
}; 

foreach (string input in words) 
{ 
    Console.WriteLine("String {0} contains {1} vowels", 
     input, rx.Matches(input).Count); 
} 

// if you really want to use LINQ 
var query = from s in words 
      select new 
      { 
       Text = s, 
       Count = rx.Matches(s).Count 
      }; 
foreach (var item in query) 
{ 
    Console.WriteLine("String {0} contains {1} vowels", item.Text, item.Count); 
} 

, 당신은 더 2 개 항목을 변경하여 원래의 코드를 단축 할 수

switch (c) 
{ 
    case 'a': 
    case 'e': 
    case 'i': 
    case 'o': 
    case 'u': 
     cnt++; 
     break; 
} 
: 배열 선언은
2) 귀하의 경우 문은 다음의 경우에 라벨로 넘어 확인 (I 위의 내 예제에서 이런 짓을했습니다)

편집 : LINQ 쿼리로 업데이트되었습니다. OP와는 크게 다른 것은 아니며, Matches 방식을 사용합니다.

+0

구문 단축에 대한 좋은 지적. LINQ Select 메서드를 사용하여 foreach를 삭제할 수도 있습니다. words.Select (input => new {input, Count = rx.Matches (input) .Count}); – HuBeZa

+0

@HuBeza : 감사합니다! 내 코드를 비슷한 LINQ 쿼리로 업데이트 한 것처럼 댓글을 달았습니다 :) 당신은 물론 lamda 쿼리를 사용하여 더욱 간단합니다. 나는 OP의 독해문과 일치하고 있었다. –

+0

가장 자세한 답변은 +0.5이고 ** 다른 경우 +0.5는 사례 비교를 무시합니다 ** – HuBeZa

3

귀하의 솔루션은 나쁘지 않다, 그러나 당신이 주장하는 경우 :

var vowels = new char[] { 'a', 'e', 'i', 'o', 'u' }; 
var words = new string[] 
      {"aesthetic", "benevolent", "abstract", 
       "capricious", "complacent", "conciliatory", 
       "devious", "diligent", "discernible","dogmatic", 
       "eccentric","fallacious","indifferent","inquisitive", 
       "meticulous","pertinent","plausible", "reticent" 
      }; 

var filter = 
    (from w in words 
    select new { w, count = w.ToLower().Count(c => vowels.Contains(c)) }). 
     Where(item => item.count > 0); 

편집 : 일부는 여기에 제안, 나는이의 ToCharArray을 제거 내가 & 또한 제로 모음 필터를 확인 tolower를 추가했다.

+2

ToCharArray() 문자열에 IEnumerable을 구현하지 않아도됩니다. –

+0

이것은 잘못되었습니다. 카운트가 0이면 항목도 포함됩니다. –

+0

@Akash : 나는 그것이 명백하다고 생각했습니다. 제로 모음을 추가했습니다. @Yuriy : 맞습니다. 명시 적 전송을 사용하여 확장 방법을 사용할 수 있습니까? 코드 예제를 게시하십시오. – HuBeZa

2

다음 솔루션은 모음이 포함되어 있고 가장 빠른 솔루션이 될 경우에만 항목을 포함합니다. C 번호가 매칭 패턴에 대한 구조를 제공 않는 정규 표현식을 사용하지 않고

var filter = from w2 in 
       (from w in words 
        select new 
        { 
         w, 
         count = 
          w.ToLower().ToCharArray().Count(
          c => c == 'a' || 
           c == 'e' || 
           c == 'i' || 
           c == 'o' || 
           c == 'u') 
        }) 
      where (w2.count > 0) 
      select w2; 
+2

좋지만'string'은'IEnumerable '을 구현하기 때문에'ToCharArray'에 대한 호출이 필요 없습니다. 그러나 'IEnumerable '확장 메서드는 Visual Studio에서 모호한 이유로 노출되지 않습니다. http://stackoverflow.com/questions/345883/why-doesnt-vs-2008-display-extension-methods-in-intellisense-for -string-class – JulianR

+0

linq은 ToCharArray없이 Count 메서드 확장을 추가하지 않습니다 .. –

+0

@JulianR, 오, 나중에 VS가 그것을 숨겼다는 것을 알았습니다. :) # –

1

모든 사람이 너무 복잡하고있다 :

Regex rx = new Regex("[aeiou]", RegexOptions.IgnoreCase); 

var query = from w in words 
      let vowelCount = rx.Matches(w).Count 
      where vowelCount != 0 
      select new { w, vowelCount }; 

은 물론 당신이 원하는 모든이 모음이 단어 (? 무엇을 말하지)과의 목록이 필요하지 않은 경우 카운트를 출력하면 루프를 사용하는 것이 더 쉽습니다.

+0

모두는 아니지만 ... 내 대답에 사용한 방법입니다. http://stackoverflow.com/questions/1585085/linq -pattern-matching/1585240 # 1585240 –

+1

아니요, 전자 메일은이 코드를 복잡하게 만들지 않습니다. 저는 정규 표현식없이 질문을 처리 할 수 ​​있습니다. 그것이 그들이 대답을주는 이유입니다. Joren에게 많이 감사드립니다. – user190560

+0

오, 네가 맞아. 아마, 나는 너의 포스트를 웬일인지보고 싶었다. – Joren