首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将ISBN10转换为ISBN13

将ISBN10转换为ISBN13
EN

Code Review用户
提问于 2017-01-27 15:43:31
回答 1查看 137关注 0票数 2

想要确认我是以最有效的方式来做这件事的。

代码语言:javascript
复制
func convrtisbn10(isbn: String) {
    var checkSum: Int = 0
    var completeISBN = ""
    let newISBN = "978" + "\(isbn)"
    let result = String(newISBN.characters.dropLast(1))
    var oddSum = 0, evenSum = 0
    let reversedArray = result.characters

    for (i, s) in reversedArray.enumerate() {

        let digit = Int(String(s))!

        if i % 2 == 0 {
            evenSum += digit
        } else {
            oddSum += digit * 3
        }
    }
    let total = evenSum + oddSum
    let remander = total % 10
    if (10 - remander) == 10 {
        checkSum = 0
    } else {
        checkSum = 10 - remander
        completeISBN = result + "\(checkSum)"
    }
    getBookInfo(completeISBN)

}
EN

回答 1

Code Review用户

发布于 2017-01-27 18:23:47

从函数名convrtisbn10中可以看出函数所做的事情。是从ISBN-10转换到ISBN-10,还是从或转向什么?为什么转换函数不返回任何内容?在函数的末尾调用getBookInfo(completeISBN):不管是什么,它都不应该是转换的一部分。

未验证输入字符串的有效性。如果输入太短或太长,结果将是无稽之谈。如果输入包含非数字,则函数将崩溃。

一个更好的函数定义可能是

代码语言:javascript
复制
func convertToISBN13(isbn10: String) -> String?

其中,参数名称指示is为ISBN-10,而函数名称指示将其转换为ISBN-13。返回值是可选的,因此我们可以返回无效输入的nil。(另一种方法是为无效输入抛出错误。)

中的类型注释

代码语言:javascript
复制
var checkSum: Int = 0

没有必要,也应该在需要变量的最窄的范围内声明变量。

设置初始值

代码语言:javascript
复制
var completeISBN = ""

隐藏程序中的错误:

代码语言:javascript
复制
if (10 - remander) == 10 {
    checkSum = 0
} else {
    checkSum = 10 - remander
    completeISBN = result + "\(checkSum)"
}

在第一种情况下,校验和没有附加到ISBN。编译器没有注意到这一点,因为completeISBN有一个定义的值。

字符串内插

代码语言:javascript
复制
let newISBN = "978" + "\(isbn)"

不需要,因为isbn已经是一个字符串:

代码语言:javascript
复制
let newISBN = "978" + isbn

变量

代码语言:javascript
复制
var oddSum = 0, evenSum = 0

不需要,所有计算都可以直接更新checkSum

没有必要对字符进行反向处理。只需从第一个开始处理它们(对奇数指数使用乘数3)。

如前所述,

代码语言:javascript
复制
    let digit = Int(String(s))!

如果s不是一个数字,将中止程序执行,应检查此数字。

我会将ISBN-13校验和的计算移到一个单独的函数中,然后可以单独使用该函数来计算或验证校验和。

将所有这些组合在一起,代码可能如下所示:

代码语言:javascript
复制
func checksumISBN13(isbn13: String) -> Int? {
    var checksum = 0
    for (position, char) in isbn13.characters.enumerated() {
        guard let digit = Int(String(char)) else {
            return nil
        }
        if position % 2 == 0 {
            checksum += digit
        } else {
            checksum += 3 * digit
        }
    }
    let remainder = checksum % 10
    if remainder == 0 {
        return 0
    } else {
        return 10 - remainder
    }
}

func convertToISBN13(isbn10: String) -> String? {

    guard isbn10.characters.count == 10 else {
        return nil
    }
    let isbn13 = "978" + String(isbn10.characters.dropLast())
    guard let checksum = checksumISBN13(isbn13: isbn13) else {
        return nil
    }
    return isbn13 + String(checksum)
}

最后,请注意,ISBN通常是用分隔符(例如"978-3-86680-192-9")分组打印的,因此另一项建议是

  • 容忍(不需要)输入字符串中的分隔符,以及
  • 以分组格式创建输出字符串。

一种更普遍的方法是定义一个ISBN类型,它可以从ISBN-10和ISBN-13字符串(带或不带校验和)初始化。只是想给你一个主意:

代码语言:javascript
复制
public struct ISBN: CustomStringConvertible {
    private let digits: [Int] // 13 digits

    public init?(isbn13: String) {
        // Verify that `isbn13` has 12 or 13 characters (ignoring separators)
        // Fill `digits`.
        // If 12 digits: append checksum.
        // If 13 digits: verify checksum.
    }

    public init?(isbn10: String) {
        // Verify that `isbn10` has 9 or 10 characters (ignoring separators)
        // Remove last character (checksum) if present.
        self.init(isbn13: "978" + isbn10)
    }

    var description: String {
        // Create and return formatted string description
    }
}
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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