Najpierw można użyć operatora łańcuchowego []
, aby uzyskać ciągi znaków zamiast substring
i usunąć zmienne pośrednie. Na przykład w przypadku dla length == 10
:
"${isbn[0]}-${isbn[1..6]}-${isbn[7..8]}-${isbn[9]}"
Teraz jest nieco powtórzeń tam. można dostać zamiast najpierw uzyskać wszystkie segmenty isbn
a następnie .join
im '-'
:
[isbn[0], isbn[1..6], isbn[7..8], isbn[9]].join('-')
A nawet dalej, zamiast o przedstawieniu isbn
za każdym razem, można zrobić listę zakresów chcesz uzyskać, a następnie je wszystkie w tym samym czasie przy użyciu collect
:
[0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
Jeśli idziesz do kodu gry w golfa, można również zrobić:
('-'+isbn)[1, 0, 2..7, 0, 8..9, 0, 10]
Zostawię to dla ciebie, aby dowiedzieć się, jak to działa, ale myślę, że to nie jest dobry pomysł, aby zostawić to na kod produkcyjny, chyba że chcesz zaskoczyć przyszłych hehe opiekunów.
Zauważ też, że format kiedy length == 13
jest taka sama jak dla length == 10
ale z innym prefiksem można następnie ponownie wykorzystać tę samą funkcję w tej sprawie. Cała funkcja (z kilku prób) byłoby:
/**
* 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'
Teraz, myślę, że istnieje kilka nieprzyjemnych zapachów w tym kodzie. Czy można isbn
być null
? Przynajmniej dla mnie nie wygląda to na funkcję, która musi zawracać sobie głowę nieważnością jej argumentu, a przynajmniej nie jest to jasne, czytając jej nazwę (powinno to być nazywane coś takiego jak formatIsbnOrNull
, jeśli oba ciągi ISBN i wartości puste są akceptowane). Jeśli wartości puste są niepoprawne, pozwól mu wysadzić się z NullPointerException
podczas uzyskiwania dostępu do isbn.length()
, aby dzwoniący wiedział, że przekazał błędny argument, zamiast cichego zwracania tej samej wartości zerowej.
To samo dotyczy końcówki return ISBN
. Czy oczekuje się, że funkcja otrzyma ciąg, który nie ma 10 ani 13 znaków? Jeśli nie, lepiej throw new IllegalArgumentException()
i niech dzwoniący wie, że nazwała to błędnie.
Wreszcie, nie jestem pewien, czy jest to najbardziej "czytelne" rozwiązanie. Innym możliwym rozwiązaniem jest posiadanie ciągu znaków w formacie, np. '###-#-######-##-#'
, a następnie zastąpienie znaków #
s znakami isbn
. Myślę, że może to być bardziej samodokumentujące:
def formatIsbn(isbn) {
def format = [
10: '#-######-##-#',
13: '###-#-######-##-#'
][isbn.length()]
def n = 0
format.replaceAll(/#/) { isbn[n++] }
}
można wyjaśnić * to rozstać? Co robi * w takim przypadku? – Gregg
@Gregg Rozkłada tablicę tak, aby wyglądała jak dwa indywidualne parametry podciągu. Powinien jednak działać bez niego. Nie mogłem ci powiedzieć, dlaczego tak się stało, dlatego zostałem kurczakiem i zostawiłem go. –