提问人:Roy Mathew 提问时间:9/7/2023 更新时间:9/8/2023 访问量:88
如果切片第一次与条件匹配,如何跳过切片中的值
How to skip values in a slice if it matches the condition first time
问:
如果条件匹配一次,如何跳过切片中的值。
func main() {
cloud := []string{"moon", "earth", "moon-light"}
for _, value := range cloud {
if strings.Contains(value, "mo") {
fmt.Println("print1")
} else if strings.Contains(value, "ear") {
fmt.Println("print2")
}
}
}
输出: 打印1 打印2 打印1
预期输出 : 打印1 打印2
谢谢!
答:
如果要根据已满足的条件跳过切片中的某些值,则可以使用标志变量来跟踪它。若要实现所需的输出,可以按如下方式修改代码:
package main
import (
"fmt"
"strings"
)
func main() {
cloud := []string{"moon", "earth", "moon-light"}
conditionMet := false // Initialize a flag variable
for _, value := range cloud {
if conditionMet {
// If the condition has already been met, skip further processing
continue
}
if strings.Contains(value, "mo") {
fmt.Println("print1")
conditionMet = true // Set the flag to true once the condition is met
} else if strings.Contains(value, "ear") {
fmt.Println("print2")
}
}
}
在此代码中,我们引入了以 false 开头的变量。当满足 “” 条件时,我们打印 “” 并设置为 true。循环的后续迭代将检查 conditionMet 是否为 true,如果是,它们将跳过进一步的处理,从而产生预期的输出 “.”conditionMet
mo
print1
conditionMet
print1 print2
此方法可确保 “” 条件仅按请求匹配一次。mo
您可以使用地图来了解是否发生了某种情况。 它比使用变量更好,因为它允许您跟踪许多条件而不会造成任何混乱。下面是您想要的示例:
cloud := []string{"moon", "earth", "moon-light"}
var conditionTracker = make(map[string]bool)
for _, value := range cloud {
if _, ok := conditionTracker["first_condition"]; !ok && strings.Contains(value, "mo") {
conditionTracker["first_condition"] = true
fmt.Println("print1")
} else if _, ok := conditionTracker["second_condition"]; !ok && strings.Contains(value, "ear") {
conditionTracker["second_condition"] = true
fmt.Println("print2")
}
}
package main
import (
"fmt"
"strings"
)
func main() {
cloud := []string{"moon", "earth", "moon-light"}
print1Flag := false
print2Flag := false
for _, value := range cloud {
if strings.Contains(value, "mo") && !print1Flag {
fmt.Println("print1")
print1Flag = true
} else if strings.Contains(value, "ear") && !print2Flag {
fmt.Println("print2")
print2Flag = true
}
}
}
该代码检查标志变量,并确保每个条件只打印一次。输出将为:print1Flag
print2Flag
print1
print2
其他答案为您的特定示例提供了基本机制,一般情况的解决方案可以使用包含标识要匹配的模式的键的映射,并且每个键的值是所需的结果/输出。
匹配密钥后,将其从地图中删除,以便不会再次匹配:
cloud := []string{"moon", "earth", "moon-light"}
match := map[string]string{
"mo": "print1",
"ear": "print2",
}
for _, value := range cloud {
for k, v := range match {
if strings.Contains(value, k) {
fmt.Println(v)
delete(find, k)
}
}
}
这可能效率较低(至少对于较大的切片和/或地图),因为它涉及两个范围循环,但如果效率/可伸缩性不如可重用性那么重要,那么这样做的好处是能够用于您可能希望通过将代码放入函数中来执行的任何一次性匹配:
func find(s []string, m map[string]string) (result []string) {
for _, c := range s {
for k, v := range m {
if strings.Contains(c, k) {
result = append(result, v)
delete(m, k)
}
}
}
return result
}
func main() {
cloud := []string{"moon", "earth", "moon-light"}
match := map[string]string{"mo": "print1", "ear": "print2"}
for _, r := range find(cloud, match) {
fmt.Println(r)
}
}
(我不确定“find”是否是此类函数的最佳名称,因为这更像是一种转换而不是查找;在您的特定用例中,我留给您一个更好的名称:))
只需稍作修改,该函数就可以成为一个过滤器,返回切片中满足匹配映射的条目(不再需要是映射,可以是子字符串匹配的简单切片)。因此,如果您要对匹配的条目执行一些处理,而不仅仅是转换它们/输出一些字符串,则首先要筛选然后遍历返回的切片:find
func filter(s []string, m []string) (result []string) {
for _, c := range s {
for i, v := range m {
if strings.Contains(c, v) {
result = append(result, c)
m = append(m[:i], m[i+1:]...)
}
}
}
return result
}
func main() {
cloud := []string{"moon", "earth", "moon-light"}
match := []string{"mo", "ear"}
for _, r := range filter(cloud, match) {
fmt.Println(r)
}
}
请注意,从切片中删除项目比从地图中删除项目要麻烦一些。
评论
if
break
moHappened := false
if strings.Contains(value, "mo") && !moHappened { fmt.Println("print1") moHappened = true }