1

ASP.NETのC#を使用して(重複を省略して)文字列のコンマ区切りリストを辞書に変換しています:

string str = "1,2, 4, 2, 4, item 3,item2, item 3"; //Just a random string for the sake of this example

どちらの方法がより効率的か疑問に思いましたか?

1-try / catchブロックの使用:

Dictionary<string, string> dic = new Dictionary<string, string>();

string[] strs = str.Split(',');
foreach (string s in strs)
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        try
        {
            string s2 = s.Trim();
            dic.Add(s2, s2);
        }
        catch
        {
        }
    }
}

2-またはContainsKey()メソッドを使用します。

string[] strs = str.Split(',');
foreach (string s in strs)
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        string s2 = s.Trim();
        if (!dic.ContainsKey(s2))
            dic.Add(s2, s2);
    }
}

編集。参加してくださった皆様、ありがとうございました!

非常に興味深い発見。以下のdtbによって提供される答えを見ると、彼はhashSetを使用する2つの方法を提案しました。ここで吹き替えます:

方法1:

var hashSet = new HashSet<string>(from s in str.Split(',')
                           where !string.IsNullOrWhiteSpace(s)
                           select s.Trim()); 

方法2:

var hashSet = new HashSet<string>();
foreach (string s in str.Split(','))
{
     if (!string.IsNullOrWhiteSpace(s))
     {
         hashSet.Add(s.Trim());
     }
}

私は彼に、パフォーマンスの面でどちらの方法が速いか、そして興味深いことに、方法2の方が速いかを尋ねました。リリースビルドの各メソッドをループ内で1,000,000回実行することにより、Stopwatchクラスを使用して行われるタイミングは次のとおりです。

Method 1: 1,440 ms average
Method 2: 1,124 ms average
4

5 に答える 5

6

辞書ではなくセットが必要な場合は、HashSet<T>クラスを使用することをお勧めします。

HashSet<T>クラス

値のセットを表します。

セットは、重複する要素を含まず、要素の順序が特定されていないコレクションです。


var hashSet = new HashSet<string>(from s in str.Split(',')
                                  where !string.IsNullOrWhiteSpace(s)
                                  select s.Trim());

または同等に

var hashSet = new HashSet<string>();
foreach (string s in str.Split(','))
{
    if (!string.IsNullOrWhiteSpace(s))
    {
        hashSet.Add(s.Trim());
    }
}
于 2012-04-08T23:14:42.873 に答える
3

辞書が必要なようには見えません。単純なLINQ式を使用すると、重複のないアイテムのリストが得られます。

var res = str
    .Split(',')
    .Where(s => !string.IsNullOrWhitespace(s))
    .Select(s => s.Trim())
    .Distinct()
    .ToList();

辞書を使用することを主張する場合は、ToDictionary代わりに次を使用できます。

var res = str
    .Split(',')
    .Where(s => !string.IsNullOrWhitespace(s))
    .Select(s => s.Trim())
    .Distinct()
    .ToDictionary(s=>s, s=>s);

通常のプログラムフローで使用try/catchすることは、意図を隠すため、強くお勧めしません。C#の例外は、条件で安全にトラップできる通常の状況ではなく、例外的な状況のために予約されていますif / then / else

于 2012-04-08T23:14:46.437 に答える
2

を使用する方法2は、例外を抑制する.ContainsKeyよりも意味論的であり、おそらくより効率的です。

于 2012-04-08T23:14:19.453 に答える
2

期待される実行フローを制御するために例外を使用することは一般的に眉をひそめ、例外をキャッチすることは費用がかかるので、私はv2を選びます。それがあなたにとって本当に重要であるならば、なぜベンチマークを設定しませんか?2の方が「効率的」だと思いますが、簡単に確認できます。

于 2012-04-08T23:16:25.930 に答える
1

ディクショナリの値を使用していない場合は、HashSet<string>代わりに使用できます。ハッシュセットに項目を追加すると、重複が自動的に削除されます。

HashSet<string> set = new HashSet<string>(
  str.Split(',')
  .Select(s => s.Trim())
  .Where(s => s.Length > 0)
);
于 2012-04-08T23:22:56.910 に答える