在Go语言中,使用整数切片进行子集检查。

huangapple go评论89阅读模式
英文:

Subset check with integer slices in Go

问题

我正在寻找一种高效的方法来检查一个切片是否是另一个切片的子集。我可以简单地迭代它们来进行检查,但我觉得应该有更好的方法。

例如:

{1, 2, 3} 是 {1, 2, 3, 4} 的子集
{1, 2, 2} 不是 {1, 2, 3, 4} 的子集

如何以高效的方式进行这种检查呢?

谢谢!

英文:

I am looking for a efficient way to check if a slice is a subset of another. I could simply iterate over them to check, but I feel there has to be a better way.

E.g.

> {1, 2, 3} is a subset of {1, 2, 3, 4}
> {1, 2, 2} is NOT a subset of {1, 2, 3, 4}

What is the best way to do this efficiently?

Thanks!

答案1

得分: 6

我认为解决子集问题最常见的方法是使用映射。

package main

import "fmt"

// subset函数返回true,如果第一个数组完全包含在第二个数组中。
// 第二个数组中必须至少有与第一个数组中相同数量的重复值。
func subset(first, second []int) bool {
    set := make(map[int]int)
    for _, value := range second {
        set[value] += 1
    }

    for _, value := range first {
        if count, found := set[value]; !found {
            return false
        } else if count < 1 {
            return false
        } else {
            set[value] = count - 1
        }
    }

    return true
}

func main() {
    fmt.Println(subset([]int{1, 2, 3}, []int{1, 2, 3, 4}))
    fmt.Println(subset([]int{1, 2, 2}, []int{1, 2, 3, 4}))
}

检查重复值的能力相对较少见。上面的代码解决了所提出的问题(参见:http://play.golang.org/p/4_7Oh-fgDQ)。如果你计划有重复值,你将不得不像上面的代码那样保持一个计数。如果不会有重复值,你可以更简洁地通过使用布尔值作为映射值来解决问题。

英文:

I think the most common way to solve a subset problem is via a map.

package main

import &quot;fmt&quot;

// subset returns true if the first array is completely
// contained in the second array. There must be at least
// the same number of duplicate values in second as there
// are in first.
func subset(first, second []int) bool {
	set := make(map[int]int)
	for _, value := range second {
		set[value] += 1
	}

	for _, value := range first {
		if count, found := set[value]; !found {
			return false
		} else if count &lt; 1 {
			return false
		} else {
			set[value] = count - 1
		}
	}

	return true
}

func main() {
	fmt.Println(subset([]int{1, 2, 3}, []int{1, 2, 3, 4}))
	fmt.Println(subset([]int{1, 2, 2}, []int{1, 2, 3, 4}))
}

The ability to check duplicate values is relatively uncommon. The code above solves the problem as asked (see: http://play.golang.org/p/4_7Oh-fgDQ) though. If you plan on having duplicate values, you'll have to keep a count like the code above does. If there will not be duplicate values, you can solve the problem more compactly by using a boolean for the map value instead of an integer.

答案2

得分: 0

如果你的切片已经排序好,这段代码可以完成任务。

package main

import "fmt"

// Subset 判断a是否是b的子列表。a和b都必须是(弱)升序的。
func Subset(a, b []int) bool {
    for len(a) > 0 {
        switch {
        case len(b) == 0:
            return false
        case a[0] == b[0]:
            a = a[1:]
            b = b[1:]
        case a[0] < b[0]:
            return false
        case a[0] > b[0]:
            b = b[1:]
        }
    }
    return true
}

func main() {
    cases := []struct {
        a, b []int
        want bool
    }{
        {[]int{1, 2, 3}, []int{1, 2, 3, 4}, true},
        {[]int{1, 2, 2}, []int{1, 2, 3, 4}, false},
    }
    for _, c := range cases {
        if Subset(c.a, c.b) != c.want {
            fmt.Printf("Subset(%v, %v) = %v, want %v\n", c.a, c.b, Subset(c.a, c.b), c.want)
        }
    }
}

这段代码定义了一个函数 Subset,用于判断切片 a 是否是切片 b 的子列表。切片 ab 都必须是(弱)升序的。在 main 函数中,定义了一些测试用例,并通过调用 Subset 函数进行测试。如果测试结果与期望结果不一致,则输出错误信息。

英文:

If your slices are sorted, this does the job.

package main

import &quot;fmt&quot;

// Subset return whether a is a sublist of b. Both a and b must be (weakly) ascending.
func Subset(a, b []int) bool {
	for len(a) &gt; 0 {
		switch {
		case len(b) == 0:
			return false
		case a[0] == b[0]:
			a = a[1:]
			b = b[1:]
		case a[0] &lt; b[0]:
			return false
		case a[0] &gt; b[0]:
			b = b[1:]
		}
	}
	return true
}

func main() {
	cases := []struct {
		a, b []int
		want bool
	}{
		{[]int{1, 2, 3}, []int{1, 2, 3, 4}, true},
		{[]int{1, 2, 2}, []int{1, 2, 3, 4}, false},
	}
	for _, c := range cases {
		if Subset(c.a, c.b) != c.want {
			fmt.Printf(&quot;Subset(%v, %v) = %v, want %v\n&quot;, c.a, c.b, Subset(c.a, c.b), c.want)
		}
	}
}

答案3

得分: -1

检查一个数组是否是另一个数组的子集的算法(使用golang)

package main

import "fmt"

func compare(arr1 []int, arr2 []int) bool {
    for _, num1 := range arr2 {
        status := false
        for _, num2 := range arr1 {
            if num1 == num2 {
                status = true
                break
            }
        }
        if !status {
            return false
        }
    }
    return true
}

func main() {
    arr1 := []int{1, 2, 3, 4, 5}
    arr2 := []int{1, 2, 3}
    if compare(arr1, arr2) {
        fmt.Println("arr2是arr1的子集")
    } else {
        fmt.Println("arr2不是arr1的子集")
    }
}

这段代码是用来检查一个数组是否是另一个数组的子集的。

英文:

Algorithm to check if an array is a subset of another array in golang

package main

import &quot;fmt&quot;

func compare(arr1 []int, arr2 []int) bool {
	for _, num1 := range arr2 {
		status := false
		for _, num2 := range arr1 {
			if num1 == num2 {
				status = true
				break
			}
		}
		if !status {
			return false
		}
	}
	return true
}
func main() {
	arr1 := []int{1, 2, 3, 4, 5}
	arr2 := []int{1, 2, 3}
	if compare(arr1, arr2) {
		fmt.Println(&quot;arr2 is subset of arr1&quot;)
	} else {
		fmt.Println(&quot;arr2 is not subset of arr1&quot;)
	}
}

huangapple
  • 本文由 发表于 2013年9月19日 01:57:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/18879109.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定