2017-07-06 9 views
1

辞書をチェックしてそのキーがあるかどうかを調べる約45のif文があります。複数のif文を使用して辞書のキーをチェックするよりも効率的な方法

private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID) 
    { 
      MessageName msgName = null; 
      List<MessageName> msgNameList = new List<MessageName>(); 
      var msgObjOuter = new MessageName(); 

      if (infoHash.ContainsKey("redis_version")) 
      { 
       msgName = new MessageName(); 
       msgName.MessageID = msgDescritionAndID["redis_version"]; 
       msgName.DiagnosticCnt = 0; 
       msgName.DiagnosticStr = infoHash["redis_version"]; 
       msgNameList.Add(msgName); 
      } 
      if (infoHash.ContainsKey("uptime_in_seconds")) 
      { 
      msgName = new MessageName(); 
      msgName.MessageID = msgDescritionAndID["uptime_in_seconds"]; 
      msgName.DiagnosticCnt = Convert.ToInt32(infoHash["uptime_in_seconds"]); 
      msgName.DiagnosticStr = ""; 
      msgNameList.Add(msgName); 
      } 
      //... 40 more if statements 
     return msgNameList; 
    } 

は、これは本当にパフォーマンスにヒットしなかったが、その辞書内のすべてのキーをチェックするためのより効率的な方法があった場合、私は思っていたし、それが挿入しなければ、それはMessageNameにオブジェクトとのインサートにしてプロパティをですそのオブジェクトをリストに追加します。私はswitch文がパフォーマンスに役立つかどうかはわかりません。

+0

使用スイッチhttps://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switchと抽出メッセージ作成。 –

+0

辞書がたくさんのキーを持っている場合は、自分の持っているものにこだわるのに興味がありません。私の答えを見ないなら。 –

答えて

1

辞書には興味のない多くのキーがあり、その場合は自分が持っているものに固執していない限り、すべてのメッセージに対して辞書ルックアップを実行する必要はありません。

これ以外の場合は、辞書に登録されているキーがわかっているため、列挙できます。

現在、キーを確認した後で値を検索しているというメッセージでは、辞書を列挙すると空き値が得られるという特別な利点があるため、別の参照が削除されます。

次に、処理したいキーについて、第2辞書からint16を参照するだけです。

あなたがより効率的にこれを処理して、このようなあなたのコードベースを減らすことができます(infoHashがしたいだけのキーを持っていると仮定した場合):

private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID) 
{ 
    MessageName msgName = null; 
    List<MessageName> msgNameList = new List<MessageName>(); 
    var msgObjOuter = new MessageName(); 
    // there is no need to perform an o(1) lookup of infoHash for 40 variables. 
    // You already have a list of keys it contains so just enumerate them. 
    foreach (KeyValuePair<string, string> info in infoHash) 
    { 
     var msg = new MessageName() { MessageID = msgDescritionAndID[info.Key] }; 
     switch (info.Key) 
     { 
      // switch all of your int16 versions first: 
      case "redis_version": 
      case "hash_int_message_2": 
      case "hash_int_message_3": 
       msg.DiagnosticCnt = Convert.ToInt32(infoHash[info.Value]); 
       break; 
      // switch on all message types getting int16 from info.Key 
      case "msg_int_message_1": 
      case "msg_int_message_2": 
       msg.DiagnosticCnt = Convert.ToInt32(msgDescritionAndID[info.Key]); 
       break; 
      // everything left over is reading value from our current info. 
      // default: 
       msg.DiagnosticStr = info.Value; 
       break; 

     } 
     msgNameList.Add(msgName); 
    } 
    return msgNameList; 
} 

infoHashがであなたの興味を持っていないキーが含まれている場合でも、あなたはこのようにそれをコーディングすることができます:別のメソッドへ

private List<MessageName> createMsgObject(Dictionary<string, string> infoHash, Dictionary<string, Int16> msgDescritionAndID) 
{ 
    MessageName msgName = null; 
    List<MessageName> msgNameList = new List<MessageName>(); 
    var msgObjOuter = new MessageName(); 
    // there is no need to perform an o(1) lookup of infoHash for 40 variables. 
    // You already have a list of keys it contains so just enumerate them. 
    foreach (KeyValuePair<string, string> info in infoHash) 
    { 
     var msg = new MessageName() { MessageID = msgDescritionAndID[info.Key] }; 
     switch (info.Key) 
     { 
      // switch all of your int16 versions first: 
      case "redis_version": 
      case "hash_int_message_2": 
      case "hash_int_message_3": 
       msg.DiagnosticCnt = Convert.ToInt32(infoHash[info.Value]); 
       break; 
      // switch on all message types getting int16 from info.Key 
      case "msg_int_message_1": 
      case "msg_int_message_2": 
       msg.DiagnosticCnt = Convert.ToInt32(msgDescritionAndID[info.Key]); 
       break; 
      // switch on all message types that have DiagnosticStr in info.Value; 
      case "msg_str_message_1": 
      case "msg_str_message_2": 
       msg.DiagnosticStr = info.Value; 

       break; 
      default: // everything left over we are not interested in 
       continue; 
       break; 

     } 
     msgNameList.Add(msgName); 
    } 
    return msgNameList; 
} 
0

switch文は、複数のifと比較して、パフォーマンスが向上します(discussed here)。私はあなたが同じ変数に同じプロパティを割り当てるあなたの40+文で複数の機会があるならば、あなたはのような何かを試みることができる、提案を持っているしかし

:次に、foreachループで

List<string> toCheckStrings1 = new List<string> { "redis_version", "something similar", };  //you can put all the strings here first 

をおあなたには、いくつかの変数(「uptime_in_seconds」用などDiagnosticCnt)、グループ化でき違ったものに異なるプロパティを割り当てる文

foreach (var match in toCheckStrings1.Intersect(infoHash.Keys)) //intersect() will give you a list of matched keys 
{ 
    msgNameList.Add(new MessageName 
    { 
     MessageID = msgDescritionAndID[match], 
     DiagnosticCnt = 0, 
     DiagnosticStr = infoHash[match] 
    }); 
} 

場合、それ以降の数を減らすことができます。

List<string> toCheckStrings2 = new List<string> { "uptime_in_seconds", "others", "etc" }; 
foreach (var match in toCheckStrings2.Intersect(infoHash.Keys)) 
{ 
    msgNameList.Add(new MessageName 
    { 
     MessageID = msgDescritionAndID[match], 
     DiagnosticCnt = Convert.ToInt32(infoHash["match"]), 
     DiagnosticStr = "" 
    }); 
} 

その他の場合も同様です。 foreachループがいくつかあるかもしれませんが、うまくいけば、if文よりもはるかに少なくなるでしょう。

EDIT

コメントで指摘したように、あなたのコードのために、それはOの束になりながら、上記の私の提案の時間複雑さはどこかにO(N)の周りになります(1)基本的にはOです( 1)。そのため、時間が問題であれば(巨大なデータセットがある場合)、ifステートメント、またはswitchと固執することが賢明でしょう。

+0

これは良いアプローチではありません。ハードコードされた 'O(1)'ルックアップからいくつかの 'O(n * m)'に行きます。これはO(1)ルックアップを再度実行するためだけに交差点を列挙するためにより多くのステップが必要です。 –

+0

実際linqの交差はO(N +)に一般化することができるO(N + M)の複雑さですが、if文を使った元のコードがより高速です。私はそれを答えに入れるように編集します。 –

+0

はい、あなたは正しいです、それはn + mです。 –

関連する問題