英文:
comparing nested slices while ignoring order
问题
在一个测试函数中,有一种情况需要比较嵌套切片。假设我有两个变量如下:
want := [][]string{{"bat"},{"nat","tan"},{"ate","eat","tea"}}
got := [][]string{{"eat","tea","ate"},{"tan","nat"},{"bat"}}
如何比较它们?
首先,我尝试使用reflect.DeepEqual
,但是结果是错误的。我还尝试了go-cmp
:
t.Run(tt.name, func(t *testing.T) {
opt := cmpopts.SortSlices(func (a, b []int) bool {
// 不确定要写什么
})
if got := groupAnagrams(tt.args.strs); !cmp.Equal(got, tt.want, opt) {
t.Errorf("groupAnagrams() = %v, want %v", got, tt.want)
}
})
英文:
In a test function, there is a case where nested slices should be compared.
Say I have two varibles like the following:
want := [][]string{{"bat"},{"nat","tan"},{"ate","eat","tea"}}
got := [][]string{{"eat","tea","ate"},{"tan","nat"},{"bat"}}
How can compare them?
First, I used reflect.DeepEqual
which was wrong, I also tried go-cmp
:
t.Run(tt.name, func(t *testing.T) {
opt := cmpopts.SortSlices(func (a, b []int) bool {
// not sure what to write
})
if got := groupAnagrams(tt.args.strs); !cmp.Equal(got, tt.want, opt) {
t.Errorf("groupAnagrams() = %v, want %v", got, tt.want)
}
})
答案1
得分: 1
对内部切片进行排序:
for _, s := range want { sort.Strings(s) }
for _, s := range got { sort.Strings(s) }
对外部切片进行排序:
sortOuter(want)
sortOuter(got)
其中sortOuter是一个函数:
func sortOuter(s [][]string) {
sort.Slice(s, func(a, b int) bool {
sa := s[a]
sb := s[b]
n := len(sa)
if n > len(sb) {
n = len(sb)
}
for i := 0; i < n; i++ {
if sa[i] != sb[i] {
return sa[i] < sb[i]
}
}
return len(sa) < len(sb)
})
}
比较:
fmt.Println(reflect.DeepEqual(got, want))
https://go.dev/play/p/SjN8gLmotjd
英文:
Sort the inner slices:
for _, s := range want { sort.Strings(s) }
for _, s := range got { sort.Strings(s) }
Sort the outer slices:
sortOuter(want)
sortOuter(got)
where sortOuter is a the function:
func sortOuter(s [][]string) {
sort.Slice(s, func(a, b int) bool {
sa := s[a]
sb := s[b]
n := len(sa)
if n > len(sb) {
n = len(sb)
}
for i := 0; i < n; i++ {
if sa[i] != sb[i] {
return sa[i] < sb[i]
}
}
return len(sa) < len(sb)
})
}
Compare:
fmt.Println(reflect.DeepEqual(got, want))
答案2
得分: 1
你可以使用sort.Slice
对内部切片进行排序,并使用testify的assert.ElementsMatch
检查外部切片是否相等:
func TestXxx(t *testing.T) {
// 切片
want := [][]string{{"bat"}, {"nat", "tan"}, {"ate", "eat", "tea"}}
got := [][]string{{"eat", "tea", "ate"}, {"tan", "nat"}, {"bat"}}
// 运行测试
t.Run("test", func(t *testing.T) {
// 对got的内部切片进行排序
for _, inner := range got {
sort.Slice(inner, func(i, j int) bool {
return inner[i] < inner[j]
})
}
// 对want的内部切片进行排序
for _, inner := range want {
sort.Slice(inner, func(i, j int) bool {
return inner[i] < inner[j]
})
}
// 匹配
assert.ElementsMatch(t, got, want)
})
}
ElementsMatch:
ElementsMatch断言指定的listA(数组、切片...)与指定的listB(数组、切片...)相等,忽略元素的顺序。如果有重复元素,则两个列表中每个元素的出现次数应该相同。
assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
英文:
You can sort inner slices using sort.Slice
as below and check if outer slices are equal using testify assert.ElementsMatch
:
func TestXxx(t *testing.T) {
// Slices
want := [][]string{{"bat"}, {"nat", "tan"}, {"ate", "eat", "tea"}}
got := [][]string{{"eat", "tea", "ate"}, {"tan", "nat"}, {"bat"}}
// Running tests
t.Run("test", func(t *testing.T) {
// Sorting got inners
for _, inner := range got {
sort.Slice(inner, func(i, j int) bool {
return inner[i] < inner[j]
})
}
// Sorting want inners
for _, inner := range want {
sort.Slice(inner, func(i, j int) bool {
return inner[i] < inner[j]
})
}
// Match
assert.ElementsMatch(t, got, want)
})
}
ElementsMatch:
> ElementsMatch asserts that the specified listA(array, slice...) is equal to specified listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, the number of appearances of each of them in both lists should match.
assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论