首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算GS1 / SSCC / UPC校验位数

计算GS1 / SSCC / UPC校验位数
EN

Code Review用户
提问于 2016-04-25 21:31:22
回答 2查看 8.3K关注 0票数 5

我试图编写一个函数,根据GS1 http://www.gs1.org/how-calculate-check-digit-manually提供的算法计算运输标签的校验位数。

第一版:我的第一次尝试

代码语言:javascript
复制
public static int GetGTINCheckDigitV1(string code)
{
    int sum = 0;
    for (int i = 0; i < code.Length; i++)
    {
        int n = int.Parse(code.Substring(code.Length - 1 - i, 1));
        sum += i % 2 == 0 ? n * 3 : n;
    }

    return sum % 10 == 0 ? 0 : 10 - sum % 10;
}

版本2:使用Reverse()

代码语言:javascript
复制
public static int GetGTINCheckDigitV2(string code)
{
    int sum = 0;
    var list = code.Reverse().ToArray();

    for (int i = 0; i < list.Length; i++)
    {
        int n = (int)Char.GetNumericValue(list[i]);
        sum += i % 2 == 0 ? n * 3 : n;
    }

    return sum % 10 == 0 ? 0 : 10 - sum % 10;
}

版本3:使用lambda

代码语言:javascript
复制
public static int GetGTINCheckDigitV3(string code)
{
    var sum = code.Reverse().Select((c, i) => (int)char.GetNumericValue(c) * (i % 2 == 0 ? 3 : 1)).Sum();
    return (10 - sum % 10) % 10;
}

我有什么可以改善这个功能的吗?或者有什么值得关注的?

EN

回答 2

Code Review用户

发布于 2016-04-26 02:00:45

看上去不错!我只有一些小小的建议。您可能不希望LINQ表达式全部放在一行上。现在我必须滚动才能看到这一切。

另一种方法是使用Enumerable.Range()创建一系列索引:

代码语言:javascript
复制
public static int GetGTINCheckDigitUsingRange(string code)
{
    var reversed = code.Reverse().ToArray();
    var sum = Enumerable
        .Range(0, reversed.Count())
        .Sum(i => (int)char.GetNumericValue(reversed[i]) * (i % 2 == 0 ? 3 : 1));        
    return (10 - sum % 10) % 10;
}

另一种选择是使用查询语法:

代码语言:javascript
复制
public static int GetGTINCheckDigitUsingQuery(string code)
{
    var reversed = code.Reverse().ToArray();
    var sum = 
       (from i in Enumerable.Range(0, reversed.Count())
        let digit = (int)char.GetNumericValue(reversed[i])
        select digit * (i % 2 == 0 ? 3 : 1)).Sum();
    return (10 - sum % 10) % 10;
}

我认为你的第三版仍然比我的好,但你可能更喜欢其中之一。Enumerable.Range()用于替换for循环,查询语法用于声明中间值(如digit)和替换嵌套循环。但是,将包含索引的lambda作为参数的Select()方法非常适合这种情况。有了足够的实践,您就可以立即达到代码看起来像第三版的地步。我很少再写循环了。我发现他们更难写,因为他们让你更多地关注“如何”而不是“什么”。

票数 2
EN

Code Review用户

发布于 2016-04-26 16:31:44

在没有参数验证的情况下,这样的公共方法是红色的。永远不要相信公共方法的任何给定输入。将null传递给该方法将抛出一个ArgumentNullException,这将是正确的异常,但提供的详细信息将具有误导性,并将向用户公开实现细节。该方法的用户不需要知道您使用的是System.Linq.Enumerable.Reverse

您没有考虑到传递的值所包含的最大位数也不应该超过17位数(SSCC)。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/126685

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档