切片显示在带有行和列的列表中
Slice display in list with row and column
我有 24 个单词的切片,我想以 4 行 6 列的列表格式显示它。我正在尝试在 Go 中实现它。
package main
import (
"fmt"
)
func main() {
words := []string{"peace", "note", "vapor", "notice", "meat", "shed", "immune", "law", "web", "security", "estate", "chat", "biology", "because", "visit", "inch", "credit", "void", "ability", "police", "crush", "begin", "matrix", "wreck"}
for i, s := range words {
fmt.Println(i, s)
}
}
所需输出:
1.peace 7.immune
2.note 8.law
3.vapor 9.web
4.notice 10.security
5.meat 11.estate
6.shed 12 chat
这是一种方法。您在所需输出中显示了 6 行,但是提到了 6 列问题。 Link to playground
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println("Hello, playground")
words := [] string{"peace", "note", "vapor", "notice", "meat", "shed", "immune", "law", "web", "security", "estate", "chat", "biology", "because", "visit", "inch", "credit", "void", "ability", "police", "crush", "begin", "matrix", "wreck"}
for i := range words {
words[i] = strconv.Itoa(i+1) + "." + words[i]
}
IterSplits(SliceSplit(words, 6), 6)
}
func IterSplits(slices[][] string, splitSize int){
for i := 0; i < splitSize; i ++ {
for _, s := range slices {
if len(s) > i {
fmt.Printf("%-15v", s[i])
}
}
println("")
}
}
func SliceSplit(aSlice[] string, splitSize int) [][]string{
var splits [][]string
for i := 0; i < len(aSlice); i += splitSize {
end := i + splitSize
if end > len(aSlice) {
end = len(aSlice)
}
splits = append(splits, aSlice[i:end])
}
return splits
}
fmt
包没有办法在终端中跳上一行。有控制字符,但一般都是terminal-dependant,所以尽量避免。
我们可以通过按行打印元素来实现 "table" 布局。如果我们有 4 行和 6 列,这意味着第一行将包含 1. 元素,然后是 7. 元素,然后是 13. 等等。第二行将包含 2. 元素,然后是 8. 元素,然后14.元素等
一般来说,我们会有 len(inputs) / cols
行,四舍五入。这就是我们如何用整数运算来表达它:
rows := (len(input) + cols - 1) / cols
并且一行中的元素将具有索引:
i := col*rows + row // col goes from 0 to cols
所以基本上我们可以使用 for
循环,遍历行,并打印行的元素。我们可以将 fmt.Printf()
与包含索引和元素的格式字符串一起使用,对所有元素使用相同的宽度(左对齐),如下所示: "%d.%-11s"
(11 是元素的宽度,如果您有更长的输入文本,请调整它)。
然而,索引并不总是具有相同的宽度。例如。索引 3
有一个数字,而 13
有两个数字。所以我们可能会用一个"padding"让每个元素和索引都占据同一个索引。此填充可能只是 spaces,并且可以使所有索引占用相同的 space 所需的数量。例如。如果我们假设我们有少于 100 个元素,那么我们可以对小于 10 的数字使用 1 space,对数字 10..99 不使用 space。
事不宜迟,这是我们简单的 table()
打印函数,它足够通用,可以获取列数,并处理其余部分:
func table(input []string, cols int) {
rows := (len(input) + cols - 1) / cols
for row := 0; row < rows; row++ {
for col := 0; col < cols; col++ {
i := col*rows + row
if i >= len(input) {
break // This means the last column is not "full"
}
padding := ""
if i < 9 {
padding = " "
}
fmt.Printf("%d.%-11s%s", i+1, input[i], padding)
}
fmt.Println()
}
}
我们来测试一下:
input := []string{
"one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "eleven", "twelve",
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
"nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four",
}
table(input, 6)
对于上面的内容,我们得到这个输出:
1.one 5.five 9.nine 13.thirteen 17.seventeen 21.twenty-one
2.two 6.six 10.ten 14.fourteen 18.eighteen 22.twenty-two
3.three 7.seven 11.eleven 15.fifteen 19.nineteen 23.twenty-three
4.four 8.eight 12.twelve 16.sixteen 20.twenty 24.twenty-four
现在让我们用 5 列进行测试,其中最后一列不会是 "complete":
table(input, 5)
这次输出将是:
1.one 6.six 11.eleven 16.sixteen 21.twenty-one
2.two 7.seven 12.twelve 17.seventeen 22.twenty-two
3.three 8.eight 13.thirteen 18.eighteen 23.twenty-three
4.four 9.nine 14.fourteen 19.nineteen 24.twenty-four
5.five 10.ten 15.fifteen 20.twenty
在 Go Playground 上试试这些。
注意#1:
以上解决方案包含 "max width" 个元素 "wired in"。如果你不能做出这样的假设,你可以先遍历元素以获得所有元素的最大宽度,并将其用于格式字符串。
这是如何完成的:
maxWidth := 0
for _, s := range input {
if len(s) > maxWidth {
maxWidth = len(s)
}
}
format := fmt.Sprintf("%%d.%%-%ds%%s", maxWidth)
那么这个format
就是在打印元素的时候要用到:
fmt.Printf(format, i+1, input[i], padding)
在 Go Playground 上试用这个改进版本。
注释 #2:
另请注意,上述算法使用的列数可能少于您传递的列数。它本着 "minimizing" 专栏的精神这样做。
例如,如果输入长度为24,而您传递了cols=10
,这意味着至少需要3行来呈现24个元素(2行最多只能在10列中显示20个元素)。但是如果使用/利用了 3 行,那么 24 个元素可以显示在少至 8 列中,因为 3*8 = 24.
我有 24 个单词的切片,我想以 4 行 6 列的列表格式显示它。我正在尝试在 Go 中实现它。
package main
import (
"fmt"
)
func main() {
words := []string{"peace", "note", "vapor", "notice", "meat", "shed", "immune", "law", "web", "security", "estate", "chat", "biology", "because", "visit", "inch", "credit", "void", "ability", "police", "crush", "begin", "matrix", "wreck"}
for i, s := range words {
fmt.Println(i, s)
}
}
所需输出:
1.peace 7.immune
2.note 8.law
3.vapor 9.web
4.notice 10.security
5.meat 11.estate
6.shed 12 chat
这是一种方法。您在所需输出中显示了 6 行,但是提到了 6 列问题。 Link to playground
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println("Hello, playground")
words := [] string{"peace", "note", "vapor", "notice", "meat", "shed", "immune", "law", "web", "security", "estate", "chat", "biology", "because", "visit", "inch", "credit", "void", "ability", "police", "crush", "begin", "matrix", "wreck"}
for i := range words {
words[i] = strconv.Itoa(i+1) + "." + words[i]
}
IterSplits(SliceSplit(words, 6), 6)
}
func IterSplits(slices[][] string, splitSize int){
for i := 0; i < splitSize; i ++ {
for _, s := range slices {
if len(s) > i {
fmt.Printf("%-15v", s[i])
}
}
println("")
}
}
func SliceSplit(aSlice[] string, splitSize int) [][]string{
var splits [][]string
for i := 0; i < len(aSlice); i += splitSize {
end := i + splitSize
if end > len(aSlice) {
end = len(aSlice)
}
splits = append(splits, aSlice[i:end])
}
return splits
}
fmt
包没有办法在终端中跳上一行。有控制字符,但一般都是terminal-dependant,所以尽量避免。
我们可以通过按行打印元素来实现 "table" 布局。如果我们有 4 行和 6 列,这意味着第一行将包含 1. 元素,然后是 7. 元素,然后是 13. 等等。第二行将包含 2. 元素,然后是 8. 元素,然后14.元素等
一般来说,我们会有 len(inputs) / cols
行,四舍五入。这就是我们如何用整数运算来表达它:
rows := (len(input) + cols - 1) / cols
并且一行中的元素将具有索引:
i := col*rows + row // col goes from 0 to cols
所以基本上我们可以使用 for
循环,遍历行,并打印行的元素。我们可以将 fmt.Printf()
与包含索引和元素的格式字符串一起使用,对所有元素使用相同的宽度(左对齐),如下所示: "%d.%-11s"
(11 是元素的宽度,如果您有更长的输入文本,请调整它)。
然而,索引并不总是具有相同的宽度。例如。索引 3
有一个数字,而 13
有两个数字。所以我们可能会用一个"padding"让每个元素和索引都占据同一个索引。此填充可能只是 spaces,并且可以使所有索引占用相同的 space 所需的数量。例如。如果我们假设我们有少于 100 个元素,那么我们可以对小于 10 的数字使用 1 space,对数字 10..99 不使用 space。
事不宜迟,这是我们简单的 table()
打印函数,它足够通用,可以获取列数,并处理其余部分:
func table(input []string, cols int) {
rows := (len(input) + cols - 1) / cols
for row := 0; row < rows; row++ {
for col := 0; col < cols; col++ {
i := col*rows + row
if i >= len(input) {
break // This means the last column is not "full"
}
padding := ""
if i < 9 {
padding = " "
}
fmt.Printf("%d.%-11s%s", i+1, input[i], padding)
}
fmt.Println()
}
}
我们来测试一下:
input := []string{
"one", "two", "three", "four", "five", "six",
"seven", "eight", "nine", "ten", "eleven", "twelve",
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
"nineteen", "twenty", "twenty-one", "twenty-two", "twenty-three", "twenty-four",
}
table(input, 6)
对于上面的内容,我们得到这个输出:
1.one 5.five 9.nine 13.thirteen 17.seventeen 21.twenty-one
2.two 6.six 10.ten 14.fourteen 18.eighteen 22.twenty-two
3.three 7.seven 11.eleven 15.fifteen 19.nineteen 23.twenty-three
4.four 8.eight 12.twelve 16.sixteen 20.twenty 24.twenty-four
现在让我们用 5 列进行测试,其中最后一列不会是 "complete":
table(input, 5)
这次输出将是:
1.one 6.six 11.eleven 16.sixteen 21.twenty-one
2.two 7.seven 12.twelve 17.seventeen 22.twenty-two
3.three 8.eight 13.thirteen 18.eighteen 23.twenty-three
4.four 9.nine 14.fourteen 19.nineteen 24.twenty-four
5.five 10.ten 15.fifteen 20.twenty
在 Go Playground 上试试这些。
注意#1:
以上解决方案包含 "max width" 个元素 "wired in"。如果你不能做出这样的假设,你可以先遍历元素以获得所有元素的最大宽度,并将其用于格式字符串。
这是如何完成的:
maxWidth := 0
for _, s := range input {
if len(s) > maxWidth {
maxWidth = len(s)
}
}
format := fmt.Sprintf("%%d.%%-%ds%%s", maxWidth)
那么这个format
就是在打印元素的时候要用到:
fmt.Printf(format, i+1, input[i], padding)
在 Go Playground 上试用这个改进版本。
注释 #2:
另请注意,上述算法使用的列数可能少于您传递的列数。它本着 "minimizing" 专栏的精神这样做。
例如,如果输入长度为24,而您传递了cols=10
,这意味着至少需要3行来呈现24个元素(2行最多只能在10列中显示20个元素)。但是如果使用/利用了 3 行,那么 24 个元素可以显示在少至 8 列中,因为 3*8 = 24.