1

次の例の例のように、パターンを照合するために正規表現を使用しています。母音を数えるために文字列を照合しています。

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)文字列に対して個々の文字をカウントするには、独自のメソッドを導出する必要がありますか?

4

4 に答える 4

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チェックとゼロ母音フィルターを追加しました。

于 2009-10-18T15:11:45.647 に答える
3

1)正規表現を使用せずに、C#はパターンを一致させるための構成を提供しますか?

ワンショットですべてを提供する正規表現ほど強力なものはありません。

2)文字列に対して個々の文字をカウントするには、独自のメソッドを導出する必要がありますか?

このアプローチはお勧めしませんが、組み込みの方法を使用してそれを実現できることを示すためだけに述べています。おそらく、 String.IndexOfを使用して、0インデックスから始まる「a」を探し、正の一致でカウンターをインクリメントしながら、ループを続けていくことができます。次に、 "e" ... "u"を繰り返しますが、正規表現やforループよりも効率が大幅に低下します。

より良いアプローチは、文字列charをcharごとにループして、既存のswitchステートメントにフィードするか、コレクションで検索することです。

LINQを使用したいので、上記のforループのアイデアを適切に書き直す方法を次に示します。このアイデアはHuBeZaのソリューションに似ているため、+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と直接矛盾します。

返されたMatchCollectionのRegex.MatchesメソッドCountプロパティを使用して、コードを短縮できます。

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つの項目を変更することで、元のコードをさらに短縮できます。

1)文字列配列宣言(上記の例でこれを実行しました)
2)ケースステートメントを次のケースラベルにフォールスルーさせます。

switch (c)
{
    case 'a':
    case 'e':
    case 'i':
    case 'o':
    case 'u':
        cnt++;
        break;
}

編集: LINQクエリで更新されました。マッチアプローチを使用するだけで、OPが持っていたものと大差ありません。

于 2009-10-18T15:56:55.087 に答える
2

次の解決策には、母音が含まれている場合にのみアイテムが含まれ、最速の解決策にもなります。

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; 
于 2009-10-18T15:27:00.633 に答える
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 };

もちろん、母音のある単語のリストは必要なく(どの単語にないのですか?)、カウントを出力するだけの場合は、ループを使用する方が簡単です。

于 2009-10-18T16:16:39.393 に答える