반복하는 동안 값 변경
다음과 같은 유형이 있다고 가정합니다.
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
노드의 속성을 반복하여 변경할 수 있습니다.
저는 다음과 같은 일을 할 수 있었으면 좋았을 것입니다.
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
그러나으로서attr
포인터가 아닙니다. 이것은 작동하지 않을 것이고 저는 해야 합니다.
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
더 간단한 방법이나 더 빠른 방법이 있습니까?에서 직접 포인터를 가져오는 것이 가능합니까?range
?
분명히 저는 반복을 위해 구조를 바꾸고 싶지 않으며 더 자세한 해결책은 해결책이 아닙니다.
아니요, 원하시는 약어는 불가능합니다.
그 이유는range
반복 중인 조각에서 값을 복사합니다.범위에 대한 사양은 다음과 같습니다.
Range expression 1st value 2nd value (if 2nd variable is present) array or slice a [n]E, *[n]E, or []E index i int a[i] E
그래서, 범위는a[i]
두 번째 값으로 배열/배열을 지정할 수 있습니다. 즉, 값이 복사되어 원래 값을 만질 수 없게 됩니다.
이 동작은 다음 코드로 설명됩니다.
x := make([]int, 3)
x[0], x[1], x[2] = 1, 2, 3
for i, val := range x {
println(&x[i], "vs.", &val)
}
코드는 범위 값과 슬라이스의 실제 값에 대해 완전히 다른 메모리 위치를 출력합니다.
0xf84000f010 vs. 0x7f095ed0bf68
0xf84000f014 vs. 0x7f095ed0bf68
0xf84000f018 vs. 0x7f095ed0bf68
그래서 당신이 할 수 있는 유일한 것은 jnml과 peter가 이미 제안한 것처럼 포인터나 인덱스를 사용하는 것입니다.그렇게.
당신은 이것과 동등한 것을 요구하는 것처럼 보입니다.
package main
import "fmt"
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
func main() {
n := Node{
[]Attribute{
{"key", "value"},
{"href", "http://www.google.com"},
},
}
fmt.Println(n)
for i := 0; i < len(n.Attr); i++ {
attr := &n.Attr[i]
if attr.Key == "href" {
attr.Val = "something"
}
}
fmt.Println(n)
}
출력:
{[{key value} {href http://www.google.com}]}
{[{key value} {href something}]}
이렇게 하면 크기가 큰 유형의 복사본을 만들 수가 많을 수 있습니다.Attribute
값, 조각 경계 검사의 희생.예제에서 다음을 입력합니다.Attribute
상대적으로 작음, 2string
슬라이스 참조: 64비트 아키텍처 컴퓨터에서 2 * 3 * 8 = 48바이트.
간단히 다음과 같이 쓸 수도 있습니다.
for i := 0; i < len(n.Attr); i++ {
if n.Attr[i].Key == "href" {
n.Attr[i].Val = "something"
}
}
하지만, 그에 상응하는 결과를 얻는 방법은range
복사본을 생성하지만 슬라이스 경계 검사를 최소화하는 절은 다음과 같습니다.
for i, attr := range n.Attr {
if attr.Key == "href" {
n.Attr[i].Val = "something"
}
}
당신의 마지막 제안을 수정하여 인덱스 전용 버전의 범위를 사용하겠습니다.
for i := range n.Attr {
if n.Attr[i].Key == "href" {
n.Attr[i].Val = "something"
}
}
제가 참조하기에 더 간단한 것 같습니다.n.Attr[i]
테스트하는 두 행 모두에서 명시적으로Key
그리고 지는 선이Val
사용하는 것보다attr
처음부터 끝까지n.Attr[i]
다른 하나는
예:
package main
import "fmt"
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []*Attribute
}
func main() {
n := Node{[]*Attribute{
&Attribute{"foo", ""},
&Attribute{"href", ""},
&Attribute{"bar", ""},
}}
for _, attr := range n.Attr {
if attr.Key == "href" {
attr.Val = "something"
}
}
for _, v := range n.Attr {
fmt.Printf("%#v\n", *v)
}
}
산출량
main.Attribute{Key:"foo", Val:""}
main.Attribute{Key:"href", Val:"something"}
main.Attribute{Key:"bar", Val:""}
대안적 접근 방식:
package main
import "fmt"
type Attribute struct {
Key, Val string
}
type Node struct {
Attr []Attribute
}
func main() {
n := Node{[]Attribute{
{"foo", ""},
{"href", ""},
{"bar", ""},
}}
for i := range n.Attr {
attr := &n.Attr[i]
if attr.Key == "href" {
attr.Val = "something"
}
}
for _, v := range n.Attr {
fmt.Printf("%#v\n", v)
}
}
출력:
main.Attribute{Key:"foo", Val:""}
main.Attribute{Key:"href", Val:"something"}
main.Attribute{Key:"bar", Val:""}
언급URL : https://stackoverflow.com/questions/15945030/change-values-while-iterating
'IT' 카테고리의 다른 글
PL/pgSQL을 사용하여 쿼리 결과를 변수에 저장 (0) | 2023.06.02 |
---|---|
루비의 대장 연산자는 무엇입니까? (0) | 2023.06.02 |
배열에 다른 배열의 값이 포함되어 있습니까? (0) | 2023.06.02 |
루비에서 해시를 복사하려면 어떻게 해야 합니까? (0) | 2023.06.02 |
SQL Server 날짜/시간 LIKE 선택? (0) | 2023.06.02 |