使用递归填充地图时出现了意外行为。

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

Unexpected behaviour when populating a map using recursion

问题

目标是计算从一组n个字符串中可以形成的所有长度为k的可能切片。

我尝试使用简单的递归来实现。只打印结果可以正常工作。将结果放入一个映射中,对于大于2的奇数k会产生一些意外的结果。

是什么导致了映射的键和它们对应的值之间的差异?

链接:https://play.golang.org/p/_SGrPRFjJ5g

package main

import (
	"fmt"
	"strings"
)

func main() {
	QQM := make(map[string][]string)
	
	states := []string{
		"a",
		"b",
	}

	var perm func(Q []string, k int)

	perm = func(Q []string, k int) {
		if k == 0 {
			QQM[strings.Join(Q, "")] = Q
			fmt.Println(QQM)
			return
		}

		for i := 0; i < len(states); i++ {
			perm(append(Q, states[i]), k-1)
		}
	}

	perm([]string{}, 4)
}
map[aaaa:[a a a a]]
map[aaaa:[a a a b] aaab:[a a a b]]
map[aaaa:[a a a b] aaab:[a a a b] aaba:[a a b a]]
...
英文:

The goal is to compute all possible slices of length k that can be formed from a set of n strings.

I tried to do it using a simple recursion. Just printing the result works fine. Putting the results in a map yields some unexpected results for odd k's greater than 2.

What causes differences between the map's keys and their corresponding values?

https://play.golang.org/p/_SGrPRFjJ5g

package main

import (
	&quot;fmt&quot;
	&quot;strings&quot;
)

func main() {
	QQM := make(map[string][]string)
	
	states := []string{
		&quot;a&quot;,
		&quot;b&quot;,
	}

	var perm func(Q []string, k int)

	perm = func(Q []string, k int) {
		if k == 0 {
			QQM[strings.Join(Q, &quot;&quot;)] = Q
			fmt.Println(QQM)
			return
		}

		for i := 0; i &lt; len(states); i++ {
			perm(append(Q, states[i]), k-1)
		}
	}

	perm([]string{}, 4)
}
map[aaaa:[a a a a]]
map[aaaa:[a a a b] aaab:[a a a b]]
map[aaaa:[a a a b] aaab:[a a a b] aaba:[a a b a]]
...

答案1

得分: 3

切片是对底层数组的一种视图。当你传递切片时,你传递的不是它们所包含的值,而是对这些值的引用。因此,当你将一个切片放入一个映射中,然后向该切片添加元素时,如果切片有足够的容量,你也会向映射中的切片添加元素。

在将切片放入映射之前,先进行复制:

newQ := make([]string, len(Q))
copy(newQ, Q)
QQM[strings.Join(Q, "")] = newQ
英文:

A slice is a view of an underlying array. When you pass slices around, you are not passing the values they contain, but references to those values. So when you put a slice to a map then add elements to that slice, if the slice has the capacity, you would be adding elements to the slice in the map as well.

Copy the slice before putting into the map:

newQ:=make([]string,len(Q))
copy(newQ,Q)
QQM[strings.Join(Q, &quot;&quot;)] = newQ

huangapple
  • 本文由 发表于 2021年5月28日 02:53:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/67728311.html
匿名

发表评论

匿名网友

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

确定