Go에지도에 키가 포함되어 있는지 확인하는 방법


답변:


1472

한 줄 답변 :

if val, ok := dict["foo"]; ok {
    //do something here
}

설명:

ifGo의 문장에는 조건문과 초기화 문장이 모두 포함될 수 있습니다. 위의 예는 다음을 모두 사용합니다.

  • 두 변수를 초기화 val합니다.지도에서 "foo"값을 받거나 "제로 값"(이 경우 빈 문자열) ok을 받고 true"foo"가 실제로지도에있는 경우 설정되는 부울을받습니다.

  • "foo"가지도에 ok있는 true경우 평가 됩니다.

"foo"가 실제로 맵에 존재하면 if명령문 의 본문 이 실행되고 val해당 범위에 로컬이됩니다.


2
이것은 더 나은이 (peterSO에서 다른 주석처럼) 어떻게 작동하는지 설명 할 수 있습니다
Chmouel Boudjnah에게

6
@Kiril var val string = ""은 동일하게 유지 val, ok :=되며 해당 블록에서만 보이는 동일한 이름을 가진 새로운 지역 변수를 만듭니다.
OneOfOne

1
좋은 대답, 당신은 이것의 복잡성이 O (1)이라고 말할 것입니까 ??
Mheni

1
@Mheni, 나는 여기 조금 늦었다는 것을 알고 있지만 이 질문 은 조회 복잡성에 대해 논의합니다. 대부분의 경우 상각 된 복잡성 은 O (1)이지만 해당 질문에 대한 답변을 읽을 가치가 있습니다.
3ocene

70
파이썬과 비교할 때 혼란스러운 구문 if key in dict.
Pranjal Mittal

129

Go 프로그래밍 언어 사양 외에도 Effective Go를 읽어야 합니다 . 지도 섹션에서 다음 과 같이 말합니다.

맵에없는 키로 맵 값을 가져 오려고하면 맵의 항목 유형에 대한 0 값이 리턴됩니다. 예를 들어, 맵에 정수가 포함 된 경우 존재하지 않는 키를 검색하면 0이 반환됩니다. 값 유형이 bool 인 맵으로 집합을 구현할 수 있습니다. 맵 항목을 true로 설정하여 값을 세트에 넣은 후 간단한 색인 작성으로 테스트하십시오.

attended := map[string]bool{
    "Ann": true,
    "Joe": true,
    ...
}

if attended[person] { // will be false if person is not in the map
    fmt.Println(person, "was at the meeting")
}

때로는 누락 된 항목을 0 값과 구별해야합니다. "UTC"에 대한 항목이 있거나지도에 전혀 없기 때문에 0입니까? 여러 과제 형태로 차별 할 수 있습니다.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

명백한 이유로 이것을 "쉼표 ok"관용구라고합니다. 이 예에서 tz가 있으면 초가 적절하게 설정되고 ok가 true가됩니다. 그렇지 않으면 초가 0으로 설정되고 ok가 false가됩니다. 멋진 오류 보고서와 함께 사용하는 함수는 다음과 같습니다.

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

실제 값에 대해 걱정하지 않고 맵에서 존재를 테스트하려면 값에 대한 일반적인 변수 대신 공백 식별자 (_)를 사용할 수 있습니다.

_, present := timeZone[tz]

57

견과류 이메일 목록 에서 검색 한 결과 Peter Froehlich가 2009 년 11 월 15 일에 게시 한 솔루션을 찾았습니다.

package main

import "fmt"

func main() {
        dict := map[string]int {"foo" : 1, "bar" : 2}
        value, ok := dict["baz"]
        if ok {
                fmt.Println("value: ", value)
        } else {
                fmt.Println("key not found")
        }
}

또는 더 간결하게

if value, ok := dict["baz"]; ok {
    fmt.Println("value: ", value)
} else {
    fmt.Println("key not found")
}

이 양식의 if명령문을 사용하면 valueok변수는 if조건 내에서만 볼 수 있습니다 .


20
키가 있는지 여부에 관심이 있고 값에 신경 쓰지 않으면을 사용할 수 있습니다 _, ok := dict["baz"]; ok. _부분은 임시 변수를 만드는 대신 거리 값을 던졌습니다.
Matthew Crumley

26

짧은 답변

_, exists := timeZone[tz]    // Just checks for key existence
val, exists := timeZone[tz]  // Checks for key existence and retrieves the value

Go Playground예가 있습니다.

더 긴 답변

유효 이동 섹션에 따라 :

맵에없는 키로 맵 값을 가져 오려고하면 맵의 항목 유형에 대한 0 값이 리턴됩니다. 예를 들어,지도에 정수가 포함 된 경우 존재하지 않는 키를 찾으려면 0을 반환합니다.

때로는 누락 된 항목을 0 값과 구별해야합니다. "UTC"에 대한 항목이 있습니까 아니면지도에 전혀 없기 때문에 빈 문자열입니까? 여러 과제 형태로 차별 할 수 있습니다.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

명백한 이유로 이것을 "쉼표 ok"관용구라고합니다. 이 예에서 tz가 있으면 초가 적절하게 설정되고 ok가 true가됩니다. 그렇지 않으면 초가 0으로 설정되고 ok가 false가됩니다. 멋진 오류 보고서와 함께 사용하는 함수는 다음과 같습니다.

func offset(tz string) int {
    if seconds, ok := timeZone[tz]; ok {
        return seconds
    }
    log.Println("unknown time zone:", tz)
    return 0
}

실제 값에 대해 걱정하지 않고 맵에서 존재를 테스트하려면 값에 대한 일반적인 변수 대신 공백 식별자 (_)를 사용할 수 있습니다.

_, present := timeZone[tz]

13

다른 답변에서 언급 한 바와 같이, 일반적인 솔루션은 사용하는 인덱스 식을할당 특별한 형태의 :

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]

이것은 좋고 깨끗합니다. 그러나 몇 가지 제한 사항이 있습니다. 특수 양식을 지정해야합니다. 오른쪽 표현식은 맵 인덱스 표현식이어야하며 왼쪽 표현식 목록에는 정확히 2 개의 피연산자가 있어야합니다. 첫 번째는 피연산자가 bool값을 할당 할 수 있고 두 번째는 피연산자가 값을 할당 할 수있는 것입니다. 이 특수 양식 결과의 첫 번째 값은 키와 연관된 값이며 두 번째 값은 지정된 키를 가진 맵에 실제로 항목이 있는지 여부를 알려줍니다 (키가 맵에있는 경우). 결과 중 하나가 필요하지 않은 경우 왼쪽 표현식 목록에 공백 식별자 도 포함될 수 있습니다 .

인덱싱 된 맵 값이 nil키를 포함하거나 포함하지 않는 경우 인덱스 식은 맵 값 유형의 0 값 으로 평가 됩니다. 예를 들어 :

m := map[int]string{}
s := m[1] // s will be the empty string ""
var m2 map[int]float64 // m2 is nil!
f := m2[2] // f will be 0.0

fmt.Printf("%q %f", s, f) // Prints: "" 0.000000

Go Playground 에서 사용해보십시오 .

따라서지도에서 0 값을 사용하지 않는 경우이를 활용할 수 있습니다.

예를 들어 값 유형이 string이고 값이 빈 문자열 ( string유형의 경우 0 값 ) 인 맵에 항목을 저장하지 않는 경우 비 특수 값을 비교하여 키가 맵에 있는지 테스트 할 수도 있습니다. 인덱스 표현식의 결과 (0의 결과) :

m := map[int]string{
    0: "zero",
    1: "one",
}

fmt.Printf("Key 0 exists: %t\nKey 1 exists: %t\nKey 2 exists: %t",
    m[0] != "", m[1] != "", m[2] != "")

출력 ( Go Playground 에서 시도 ) :

Key 0 exists: true
Key 1 exists: true
Key 2 exists: false

실제로 우리는 0 값을 맵에 저장하지 않는 경우가 많으므로 자주 사용할 수 있습니다. 예를 들어 인터페이스와 함수 유형은 0 값을 가지며, nil종종 맵에 저장하지 않습니다. 따라서 키가지도에 있는지 테스트하는 것은 키와 비교하여 수행 할 수 있습니다 nil.

이 "기술"을 사용하면 또 다른 장점이 있습니다. 여러 키가 존재하는지 간단한 방법으로 확인할 수 있습니다 (특별한 "쉼표"형식으로는 수행 할 수 없습니다). 이에 대한 추가 정보 : 한 조건에서 키가 여러 맵에 존재하는지 확인

존재하지 않는 키로 인덱싱 할 때 값 유형의 0 값을 가져 오면 값이있는 맵을 bool편리하게 세트 로 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

set := map[string]bool{
    "one": true,
    "two": true,
}

fmt.Println("Contains 'one':", set["one"])

if set["two"] {
    fmt.Println("'two' is in the set")
}
if !set["three"] {
    fmt.Println("'three' is not in the set")
}

출력합니다 ( Go Playground 에서 시도하십시오 ).

Contains 'one': true
'two' is in the set
'three' is not in the set

관련 참조 : 고유 한 문자열을 포함하는 배열을 어떻게 만들 수 있습니까?


1
무엇 Tvar v, ok T = a[x]? ok바보 가 아니 어야합니까?
Kokizzu '

2
@Kokizzu 변수 선언의 일반적인 형태입니다. 처음에 우리는 map이 type map[bool]bool이고 Tis bool인 경우에만 작동 (컴파일) 할 것이라고 생각할 수도 있지만 map이 type map[interface{}]bool이고 Tis 인 경우에도 작동합니다 interface{}. 또한 bool기본 유형으로 사용되는 사용자 정의 유형에서도 작동합니다 . Go Playground 에서 모두 참조하십시오 . 따라서 해당 형식은로 대체되는 여러 유형으로 유효 T하므로 일반 T이 사용되는 이유 입니다. 의 종류는 ok되는 무엇이든 할 수있다 형식화되지 않은이bool 할당 할 수 있습니다.
icza

7

더 나은 방법은 여기

if _, ok := dict["foo"]; ok {
    //do something here
}

4
    var d map[string]string
    value, ok := d["key"]
    if ok {
        fmt.Println("Key Present ", value)
    } else {
        fmt.Println(" Key Not Present ")
    }

3
    var empty struct{}
    var ok bool
    var m map[string]struct{}
    m = make(map[string]struct{})
    m["somestring"] = empty


    _, ok = m["somestring"]
    fmt.Println("somestring exists?", ok) 
    _, ok = m["not"]
    fmt.Println("not exists?", ok)

그런 다음 maps.go를 실행하십시오. 존재하지 않는가? 그릇된


int의 필요성을 제거합니다
Lady_Exotel

기여해 주셔서 감사하지만 현재 답변이 문제를 잘 다루고 있다고 생각합니다. 여기서 말하는 내용에서 귀하의 답변은 Go 유형의 질문에 설정된 최상의 구현 방법에 더 적합합니다 .
tomasz

_, ok = m["somestring"]해야=_, ok := m["somestring"]
Elroy 젝슨에게

3

"인덱스 표현식"에 언급되어 있습니다.

특수 양식의 지정 또는 초기화에 사용되는 map [K] V 유형의 맵에서 인덱스 표현식

v, ok = a[x] 
v, ok := a[x] 
var v, ok = a[x]

추가 유형화되지 않은 부울 값을 생성합니다. 키 x가 맵에 있으면 ok 값은 true이고, 그렇지 않으면 false입니다.


1

이 목적으로 두 가지 값을 할당 할 수 있습니다. 아래 샘플 프로그램을 확인하십시오

package main

import (
    "fmt"
)

func main() {
    //creating a map with 3 key-value pairs
    sampleMap := map[string]int{"key1": 100, "key2": 500, "key3": 999}
    //A two value assignment can be used to check existence of a key.
    value, isKeyPresent := sampleMap["key2"]
    //isKeyPresent will be true if key present in sampleMap
    if isKeyPresent {
        //key exist
        fmt.Println("key present, value =  ", value)
    } else {
        //key does not exist
        fmt.Println("key does not exist")
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.