InputOutput
abc abc___
a a___
abcdeabcde_
Attempt
package main
import "fmt"
import "unicode/utf8"
func main() {
input := "abc"
if utf8.RuneCountInString(input) == 1 {
fmt.Println(input + "_____")
} else if utf8.RuneCountInString(input) == 2 {
fmt.Println(input + "____")
} else if utf8.RuneCountInString(input) == 3 {
fmt.Println(input + "___")
} else if utf8.RuneCountInString(input) == 4 {
fmt.Println(input + "__")
} else if utf8.RuneCountInString(input) == 5 {
fmt.Println(input + "_")
} else {
fmt.Println(input)
}
}
returns
abc___
Discussion
Although the code is creating the expected output, it looks very verbose and devious.
Question
Is there a concise way?
The strings package has a Repeat
function, so something like
input += strings.Repeat("_", desiredLen - utf8.RuneCountInString(input))
would be simpler. You should probably check that desiredLen
is smaller than inpult length first.
You could just do input += "_"
in a cycle, but that would allocate unnecessary strings. Here is a version that doesn't allocate more than it needs:
const limit = 6
func f(s string) string {
if len(s) >= limit {
return s
}
b := make([]byte, limit)
copy(b, s)
for i := len(s); i < limit; i++ {
b[i] = '_'
}
return string(b)
}
Playground: http://play.golang.org/p/B_Wx1449QM.
You can also do this efficiently without loops and "external" function calls, by slicing a prepared "max padding" (slice out the required padding and simply add it to the input):
const max = "______"
func pad(s string) string {
if i := utf8.RuneCountInString(s); i < len(max) {
s += max[i:]
}
return s
}
Using it:
fmt.Println(pad("abc"))
fmt.Println(pad("a"))
fmt.Println(pad("abcde"))
Output (try it on the Go Playground):
abc___
a_____
abcde_
Notes:
len(max)
is a constant (because max
is a constant): Spec: Length and capacity:
The expression
len(s)
is constant ifs
is a string constant.
Slicing a string
is efficient:
An important consequence of this slice-like design for strings is that creating a substring is very efficient. All that needs to happen is the creation of a two-word string header. Since the string is read-only, the original string and the string resulting from the slice operation can share the same array safely.