Dictionary Key look up with variable length inputs I am decoding GS1 barcodes and need to match up application identifiers with relevant data about them.




00    SSCC (Serial Shipping Container Code)   N2+N18  FALSE   SSCC 
01    Global Trade Item Number (GTIN)         N2+N14  FALSE   GTIN 
02    GTIN of Contained Trade Items           N2+N14  FALSE   CONTENT 
10    Batch or Lot Number                     N2+X.20 TRUE    BATCH/LOT 
11    Production Date (YYMMDD)                N2+N6   FALSE   PROD DATE 
12    Due Date (YYMMDD)                       N2+N6   FALSE   DUE DATE 
13    Packaging Date (YYMMDD)                 N2+N6   FALSE   PACK DATE 
15    Best Before Date (YYMMDD)               N2+N6   FALSE   BEST BEFORE or BEST BY 
16    Sell By Date (YYMMDD)                   N2+N6   FALSE   SELL BY 
17    Expiration Date (YYMMDD)                N2+N6   FALSE   USE BY OR EXPIRY 
20    Variant Number                          N2+N2   FALSE   VARIANT 
21    Serial Number                           N2+X.20 TRUE    SERIAL 
240   Additional Item Identification          N3+X.30 TRUE    ADDITIONAL ID 
241   Customer Part Number                    N3+X.30 TRUE    CUST. PART NO. 
242   Made-to-Order Variation Number          N3+N.6  TRUE    MTO VARIANT 
243   Packaging Component Number              N3+X.20 TRUE    PCN 
250   Secondary Serial Number                 N3+X.30 TRUE    SECONDARY SERIAL 
251   Reference to Source Entity              N3+X.30 TRUE    REF. TO SOURCE 
253   Global Document Type Identifier (GDTI)  N3+N13+XTRUE    GDTI 
254   GLN Extension Component                 N3+X.20 TRUE    GLN EXTENSION COMPONENT 
255   Global Coupon Number (GCN)              N3+N13+NTRUE    GCN 
30    Count of Items (Variable Measu ...      N2+N..8 TRUE    VAR. COUNT 
3100  Net weight  kilograms (Var... )     N4+N6   FALSE   NET WEIGHT (kg) 
...



Full list here.

This is how I identify them:



public Dictionary&lt;int, Tuple&lt;string, string, bool, string&gt;&gt; gs1AiDict { get; private set; } 

var aiDataOut = new Tuple&lt;string, string, bool, string&gt;("","",false,"");

//Get first 4 digits (max identifier length)
//the string input pi might look like this: ~10000123
int applicationIdentifier = Convert.ToInt16(pi.Substring(1,4));
//Try to find an identifier with 2 digits.
if (gs1AiDict.TryGetValue(applicationIdentifier / 100, out aiDataOut))
{
    //assign found data to tuple
    id = aiDataOut.Item1;
    format = aiDataOut.Item2;
    func = aiDataOut.Item3;
    abrv = aiDataOut.Item4;
}
//look up the first 3 digits
else
{
    if (gs1AiDict.TryGetValue(applicationIdentifier / 10, out aiDataOut))
    {
        id = aiDataOut.Item1;
        format = aiDataOut.Item2;
        func = aiDataOut.Item3;
        abrv = aiDataOut.Item4;
    }
    //look up first 4 digits
    else
    {
        if (gs1AiDict.TryGetValue(applicationIdentifier, out aiDataOut))
        {
            id = aiDataOut.Item1;
            format = aiDataOut.Item2;
            func = aiDataOut.Item3;
            abrv = aiDataOut.Item4;
        }
        //no identifiers are 5 digits
        else
        {
         console.log("No Application Identifier found!");
        }
    }
}


My tests have worked wonderfully, but my issue is the readability and efficiency of this solution. Are 3 dictionary key look ups for about 140 keys too much?
Code duplication is a sin

You could use shorter and more readable code using a simple for loop:

int applicationIdentifier = Convert.ToInt16(pi.Substring(1,4));
for (int i = 100; i &gt;= 1; i /= 10)
{
    int maybeId = applicationIdentifier / i;
    if (gs1AiDict.TryGetValue(maybeId, out aiDataOut))
    {
        id = aiDataOut.Item1;
        format = aiDataOut.Item2;
        func = aiDataOut.Item3;
        abrv = aiDataOut.Item4;
        return;
    }
}   
Console.WriteLine("No Application Identifier found!");


You should also consider making your data object something along the lines of a Dicitionary&lt;int, ApplicationInfo&gt;, that 4-member tuple doesn't help readibility. Then you could also return an ApplicationInfo object instead of copying the fields to local variables.