如果切片第一次与条件匹配,如何跳过切片中的值

How to skip values in a slice if it matches the condition first time

提问人:Roy Mathew 提问时间:9/7/2023 更新时间:9/8/2023 访问量:88

问:

如果条件匹配一次,如何跳过切片中的值。

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

谢谢!

字符串 切片

评论

2赞 icza 9/7/2023
目前尚不清楚要跳过的内容。如果最后一个条件为真,您想跳过更多元素吗?如果是这样,请使用 .ifbreak
0赞 Soc 9/8/2023
不完全确定您要实现的目标,但如果您只想第一个条件只为真一次,那么您可以使用初始化的布尔标志来标记何时发生这种情况,然后只需在 IF 语句上添加该布尔标志与您已经拥有的内容相结合,即moHappened := falseif strings.Contains(value, "mo") && !moHappened { fmt.Println("print1") moHappened = true }

答:

2赞 Wise Chimpanzee 9/7/2023 #1

如果要根据已满足的条件跳过切片中的某些值,则可以使用标志变量来跟踪它。若要实现所需的输出,可以按如下方式修改代码:

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,如果是,它们将跳过进一步的处理,从而产生预期的输出 “.”conditionMetmoprint1conditionMetprint1 print2

此方法可确保 “” 条件仅按请求匹配一次。mo

3赞 Soroosh 9/7/2023 #2

您可以使用地图来了解是否发生了某种情况。 它比使用变量更好,因为它允许您跟踪许多条件而不会造成任何混乱。下面是您想要的示例:

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")
    }
}
0赞 Vishwa Ratna 9/7/2023 #3
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
        }
    }
}

该代码检查标志变量,并确保每个条件只打印一次。输出将为:print1Flagprint2Flag

print1
print2
0赞 Deltics 9/8/2023 #4

其他答案为您的特定示例提供了基本机制,一般情况的解决方案可以使用包含标识要匹配的模式的键的映射,并且每个键的值是所需的结果/输出。

匹配密钥后,将其从地图中删除,以便不会再次匹配:

    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)
    }
}

请注意,从切片中删除项目比从地图中删除项目要麻烦一些。

游乐场在这里。