我有以下代码,这是有效的,但我想知道是否有一种"groovier"方式这样做:
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
* */
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
def part1 = isbn.substring(0, 1)
def part2 = isbn.substring(1, 7)
def part3 = isbn.substring(7, 9)
def part4 = isbn.substring(9, 10)
return "${part1}-${part2}-${part3}-${part4}"
} else if (isbn?.length() == 13) {
def part1 = isbn.substring(0, 3)
def part2 = isbn.substring(3, 4)
def part3 = isbn.substring(4, 10)
def part4 = isbn.substring(10, 12)
def part5 = isbn.substring(12, 13)
return "${part1}-${part2}-${part3}-${part4}-${part5}"
} else {
return isbn
}
}
Run Code Online (Sandbox Code Playgroud)
您可以先使用[]字符串运算符来获取子字符串,而不是substring删除中间变量.例如,在以下情况下length == 10:
"${isbn[0]}-${isbn[1..6]}-${isbn[7..8]}-${isbn[9]}"
Run Code Online (Sandbox Code Playgroud)
现在,那里有一些重复.您可以首先获取所有isbn细分,然后.join使用'-':
[isbn[0], isbn[1..6], isbn[7..8], isbn[9]].join('-')
Run Code Online (Sandbox Code Playgroud)
而且,更进一步,isbn您可以列出您想要获得的范围,而不是每次都参考,然后使用collect以下方法同时获取它们:
[0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
Run Code Online (Sandbox Code Playgroud)
如果您打算打高尔夫球,您还可以:
('-'+isbn)[1, 0, 2..7, 0, 8..9, 0, 10]
Run Code Online (Sandbox Code Playgroud)
我会留给你弄清楚它是如何工作的,但我想将它留在生产代码上可能不是一个好主意,除非你想让未来的维护者感到惊讶.
另外,请注意,格式何时length == 13与for length == 10具有相同但具有不同的前缀,然后您可以在该情况下重用相同的函数.整个功能(有几个测试)将是:
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
**/
def formatIsbn(isbn) {
switch (isbn?.length()) {
case 10: return [0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
case 13: return isbn.take(3) + '-' + formatIsbn(isbn.drop(3))
default: return isbn
}
}
assert formatIsbn('abcdefghij') == 'a-bcdefg-hi-j'
assert formatIsbn('abcdefghijklm') == 'abc-d-efghij-kl-m'
Run Code Online (Sandbox Code Playgroud)
现在,我认为该代码中有一些难闻的气味.能isbn是null?至少在我看来,这看起来不像是一个需要打扰其论证的无效性的函数,或者至少通过读取它的名称并不清楚(formatIsbnOrNull如果ISBN字符串和空值都是公认).如果null值无效,那么让它NullPointerException在访问时爆炸,isbn.length()以便调用者知道他们已经传递了错误的参数,而不是静默地返回相同的null.
最后也是如此return ISBN.是否希望该函数接收一个既不是10个也不是13个字符的字符串?如果不是,那就更好了throw new IllegalArgumentException(),让来电者知道他们错误地拨了电话.
最后,我不确定这是否是最"可读"的解决方案.另一种可能的解决方案是使用格式的字符串'###-#-######-##-#',然后用字符替换#s isbn.我认为它可能更自我记录:
def formatIsbn(isbn) {
def format = [
10: '#-######-##-#',
13: '###-#-######-##-#'
][isbn.length()]
def n = 0
format.replaceAll(/#/) { isbn[n++] }
}
Run Code Online (Sandbox Code Playgroud)
不知道我是否更喜欢这个。我也会将位置图设为静态最终图。
private isbnify(String isbn) {
def dashesAt = [ 10: [[0,1], [1,7], [7,9], [9,10]],
13: [[0,3], [3,4], [4,10], [10,12], [12,13]]]
def dashes = dashesAt[isbn?.length()]
(dashes == null) ? isbn
: dashes.collect { isbn.substring(*it) }.join('-')
}
Run Code Online (Sandbox Code Playgroud)
在我看来,范围可以减少混乱:
private isbnify3(String isbn) {
def dashesAt = [ 10: [0, 1..6, 7..8, 9],
13: [0..2, 3, 4..9, 10..11, 12]]
def dashes = dashesAt[isbn?.length()]
dashes == null ? isbn : dashes.collect { isbn[it] }.join("-")
}
Run Code Online (Sandbox Code Playgroud)
使用带有两个累加器的注入,也应该很容易制作破折号位置列表版本。