想要确认我是以最有效的方式来做这件事的。
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)
}发布于 2017-01-27 18:23:47
从函数名convrtisbn10中可以看出函数所做的事情。是从ISBN-10转换到ISBN-10,还是从或转向什么?为什么转换函数不返回任何内容?在函数的末尾调用getBookInfo(completeISBN):不管是什么,它都不应该是转换的一部分。
未验证输入字符串的有效性。如果输入太短或太长,结果将是无稽之谈。如果输入包含非数字,则函数将崩溃。
一个更好的函数定义可能是
func convertToISBN13(isbn10: String) -> String?其中,参数名称指示is为ISBN-10,而函数名称指示将其转换为ISBN-13。返回值是可选的,因此我们可以返回无效输入的nil。(另一种方法是为无效输入抛出错误。)
中的类型注释
var checkSum: Int = 0没有必要,也应该在需要变量的最窄的范围内声明变量。
设置初始值
var completeISBN = ""隐藏程序中的错误:
if (10 - remander) == 10 {
checkSum = 0
} else {
checkSum = 10 - remander
completeISBN = result + "\(checkSum)"
}在第一种情况下,校验和没有附加到ISBN。编译器没有注意到这一点,因为completeISBN有一个定义的值。
字符串内插
let newISBN = "978" + "\(isbn)"不需要,因为isbn已经是一个字符串:
let newISBN = "978" + isbn变量
var oddSum = 0, evenSum = 0不需要,所有计算都可以直接更新checkSum。
没有必要对字符进行反向处理。只需从第一个开始处理它们(对奇数指数使用乘数3)。
如前所述,
let digit = Int(String(s))!如果s不是一个数字,将中止程序执行,应检查此数字。
我会将ISBN-13校验和的计算移到一个单独的函数中,然后可以单独使用该函数来计算或验证校验和。
将所有这些组合在一起,代码可能如下所示:
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字符串(带或不带校验和)初始化。只是想给你一个主意:
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
}
}https://codereview.stackexchange.com/questions/153778
复制相似问题