2017-07-06 2 views
1

Ich habe rund 45 if-Anweisungen, die das Wörterbuch überprüfen, um zu sehen, ob es diesen Schlüssel hat.Effizienter alternativer Weg als die Verwendung mehrerer if-Anweisungen zum Überprüfen von Schlüsseln in einem Wörterbuch

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; 
    } 

Das hat nicht wirklich einen Erfolg auf Leistung hat, aber ich frage mich, ob es eine effizientere Art und Weise all Schlüssel in diesem Wörterbuch zu überprüfen war, und wenn sie es ist Eigenschaft nicht einfügen in ein Message Objekt und Einsatz dieses Objekt in eine Liste. Ich weiß nicht, ob Switch-Anweisungen in der Leistung helfen würden.

+0

Verwenden Schalter https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/switch und Extraktnachrichtenerstellung in der separaten Verfahren. –

+0

Wenn Ihr Wörterbuch groß ist mit vielen Schlüsseln, an denen Sie nicht interessiert sind, bleiben Sie bei dem, was Sie haben. Wenn nicht meine Antwort sehen. –

Antwort

1

Es ist nicht notwendig, eine Wörterbuchsuche für alle Ihre Nachrichten durchzuführen, es sei denn, Ihr Wörterbuch enthält viele Schlüssel, die Sie nicht interessieren. In diesem Fall bleiben Sie bei dem, was Sie haben.

Andernfalls wissen Sie bereits, welche Schlüssel im Wörterbuch sind, so dass Sie sie einfach aufzählen können.

Für die Nachricht, dass Sie gerade den Wert nach der Suche nach dem Schlüssel suchen, werden Sie eine weitere Suche ausschalten, da das Aufzählen des Wörterbuchs den zusätzlichen Vorteil hat, den Wert kostenlos zu erhalten.

Dann ist alles, was Sie tun müssen, das int16 aus Ihrem zweiten Wörterbuch nach den Schlüsseln zu suchen, die Sie verarbeiten möchten.

Sie können dies effizienter verarbeiten und Ihre Code-Basis wie folgt reduzieren (unter der Annahme infoHash hat nur Schlüssel Sie möchten):

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; 
} 

Auch wenn infoHash enthält Schlüssel Ihr nicht interessiert, können Sie es wie dieser Code :

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-Anweisungen helfen in der Leistung, im Vergleich zu mehreren Wenns, wie discussed here.

Jedoch habe ich einen Vorschlag, wenn es mehrere Gelegenheiten in Ihrem 40+ Aussagen sind, wo Sie die gleichen Eigenschaften auf die gleichen Variablen zuweisen, Sie so etwas wie versuchen könnte:

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

Dann sind Sie mit einer foreach-Schleife if-Anweisungen können die Anzahl der reduzieren

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] 
    }); 
} 

Und da Sie verschiedene Eigenschaften für einige Variablen (zB DiagnosticCnt für „uptime_in_seconds“) zuordnen, können Sie Gruppe diejenigen anders:

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 = "" 
    }); 
} 

Und so weiter für andere Fälle. Obwohl es mehrere foreach Schleifen sein könnte, wäre es hoffentlich viel weniger als 45 if-Anweisungen.

EDIT

Wie in den Kommentaren darauf hingewiesen, die Zeitkomplexität von meinem Vorschlag oben würde irgendwo um O (N), während für Ihren Code wäre es ein Bündel von O (1) sein, das ist im Grunde O (1). Wenn Zeit eine Rolle spielt (wenn Sie riesige Datensätze haben), wäre es sinnvoller, wenn Sie einfach bei if Anweisungen bleiben oder switch.

+0

Dies ist kein guter Ansatz. Sie gehen von fest codierten 'O (1)' - Lookups zu mehreren 'O (n * m)', die noch mehr Schritte erfordern, um die Schnittmenge nur aufzuzählen, um erneut eine O (1) - Suche durchzuführen. –

+0

Eigentlich ist der Schnittpunkt von linq O (N + M) -Komplexität, die zu O (N) verallgemeinert werden kann, aber ich sehe Ihren Punkt, der ursprüngliche Code, der if-Anweisungen verwendet, ist schneller. Ich werde es bearbeiten, um es in die Antwort aufzunehmen. –

+0

Ja, Sie haben Recht, es ist n + m. –

Verwandte Themen