5
\$\begingroup\$

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<int, Tuple<string, string, bool, string>> gs1AiDict { get; private set; } 

var aiDataOut = new Tuple<string, string, bool, string>("","",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?

\$\endgroup\$
3
\$\begingroup\$

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 >= 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<int, ApplicationInfo>, that 4-member tuple doesn't help readibility. Then you could also return an ApplicationInfo object instead of copying the fields to local variables.

\$\endgroup\$
  • \$\begingroup\$ Indeed that function is much cleaner. Regarding the use of "Application Info" to hold the data: could you point me to a use of that? When I was researching how to get multiple parameters per key, all I found were Tuples. \$\endgroup\$ – user4067565 Nov 17 '14 at 16:18
  • \$\begingroup\$ @Phyre ApplicationInfo is a name I made up, it's not a existing type. I was suggesting that you should create a class that holds a single entry of application information. \$\endgroup\$ – Rotem Nov 17 '14 at 16:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.