Swift 사전에 키가 포함되어 있는지 확인하고 해당 값을 가져 오는 경우


260

현재 비어 있지 않은 Swift 사전에 주어진 키가 포함되어 있는지 확인하고 동일한 사전에서 하나의 값을 얻기 위해 다음과 같은 (서투른) 코드 조각을 사용하고 있습니다.

어떻게 Swift에 더 우아하게 넣을 수 있습니까?

// excerpt from method that determines if dict contains key
if let _ = dict[key] {
    return true
}
else {
    return false
}

// excerpt from method that obtains first value from dict
for (_, value) in dict {
    return value
}

indexForKey더 명확하고 명시 적이라고 생각되면 사용할 수 있습니다 . stackoverflow.com/a/29299943/294884
Fattie

아주 자주 당신이 원하는 기본적으로 : cityName:String = dict["city"] ?? "" (가) ?? """그러한 키가 존재하지 않는 경우는, 빈 반환"여기에 기본적으로 의미한다.
Fattie

답변:


481

당신은 필요하지 않습니다 어떤 이 사전에 이미 무엇 때문에이 작업을 수행하는 특수 코드를. 당신이 가져올 때 dict[key]당신이 알고 하지 않습니다 다시 얻을 수있는 옵션 때문에, 사전에 키가 포함되어 있는지 여부를 nil(그리고 값을 포함).

당신이 경우에 따라서, 단지 사전이 키가 포함되어 있는지 여부를 질문에 대답 할 질문 :

let keyExists = dict[key] != nil

값을 원하고 사전에 키가 포함되어 있다는 것을 알고 있다면 다음과 같이 말합니다.

let val = dict[key]!

그러나 일반적으로 발생하는 것처럼 키에 키가 있는지 알지 못하는 경우 키를 가져 와서 사용하고 싶지만 존재하는 경우에만 다음과 같이 사용하십시오 if let.

if let val = dict[key] {
    // now val is not nil and the Optional has been unwrapped, so use it
}

6
나는 따르지 않는다. 방금 가치를 얻었습니다 (두 번). 무엇을 더 원하십니까?
matt

"첫번째 가치"와 같은 것은 없습니다. 사전은 순서가 없습니다. 키가없는 값만 원하면이라고 말합니다 dict.values.
matt

1
dict.values불투명 하기 때문에주의하십시오 . 당신은 그것을 통해 순환 할 수 있지만 그게 다야. (좋아, 전부는 아니지만 나에게 유머.) 배열로 통합하려면을 가져 가십시오 dict.values.array.
matt

1
@bubakazouba 이것을 시도하십시오 : let d = ["hey":"ho"]; let s = d["hey"]; print(s)그것은 항상 그렇듯이 선택 사항입니다.
matt

1
@Kross 매우 심오한 질문이지만 따로 ​​문의하십시오.
매트

68

왜 간단히 확인하지 dict.keys.contains(key)않습니까? dict[key] != nil값이 nil 인 경우 검사 가 작동하지 않습니다. [String: String?]예를 들어 사전과 마찬가지로 .


2
또는 그냥 쓰는 대신 이 경우에 if let val = dict[key]사용할 수 있습니다 if let val = dict[key] as? String.
Okhan Okbay

.keys.contains는 키가 존재하는지 또는 값이 nil인지 구별하는 데 도움이되지 않습니다. 어쩌면 이전 버전의 어쩌면? 스위프트 4에서 나를 위해 작동하지 않습니다.
Rowan Gontier

8
(1) 호출 dict.keys하면 모든 키로 배열을 생성 한 다음 (2) 하나를 찾을 때까지 모든 키를 순서대로 검사합니다 (또는 없음). 나는 당신이 사건을 해결하려고 노력하고 있다는 것을 알고 [String: String?]있지만 그 해결책에 매우주의를 기울일 것입니다.
Charles Charles

3
@ Charles가 언급했듯이 사전을 사용하면 얻을 수있는 빠른 조회 이점을 제거 하므로이 옵션에 대해서는 조언하지만 여전히 유효한 옵션입니다.
businesscasual

4
직접 사전 액세스의 이론적 (해시 함수 구현에 따라 다름) O (1) 대신 복잡성 O (n)이있는이 방법을 사용 해서는 안됩니다 .
Krypt

45

let keyExists = dict[key] != nil사전에 키가 있지만 값이 nil 인 경우 허용되는 답변 이 작동하지 않습니다.

사전에 키가 전혀 포함되어 있지 않은지 확인하려면 이것을 사용하십시오 (Swift 4에서 테스트).

if dict.keys.contains(key) {
  // contains key
} else { 
  // does not contain key
}

3
한의 대답과 같습니다.
Declan McKenna

1
== nil사전에 선택적 값이 있어도 확인 이 작동합니다. 조회 결과가로 래핑되기 때문 Optional입니다. 반면에 조회 된 값이 실제로 nil없는 것이 아닌지 확인 하려면을 사용할 수 있습니다 == .some(nil).
jedwidz

1
다른 방법의 O (1) 조회와 비교하여이 방법을 사용하는 효율성을 추가 할 것입니다. 나는 그것의 O (n)이 조회 생각
알베르토 베가

1
@ AlbertoVega-MSFT O(1)입니다. 참조 : github.com/apple/swift-evolution/blob/master/proposals/... 당신은 그것이 무엇을 생각하게 O(n)?
알렉산더-복원 모니카

1
에 대한 문서 Dictionary.Keys.contains(...)기능은 여기 가 가지고 말한다 O(n)곳, 복잡성을 n시퀀스의 길이입니다.
Adil Hussain

5

@matt에서 필요한 것을 얻었지만 키 값을 빠르게 얻을 수있는 방법을 원하거나 해당 키가 없으면 첫 번째 값을 얻는 경우 :

extension Dictionary {
    func keyedOrFirstValue(key: Key) -> Value? {
        // if key not found, replace the nil with 
        // the first element of the values collection
        return self[key] ?? first(self.values)
        // note, this is still an optional (because the
        // dictionary could be empty)
    }
}

let d = ["one":"red", "two":"blue"]

d.keyedOrFirstValue("one")  // {Some "red"}
d.keyedOrFirstValue("two")  // {Some "blue"}
d.keyedOrFirstValue("three")  // {Some "red”}

실제로 첫 번째 값으로 얻을 수있는 것을 보장하지는 않으며이 경우에는 빨간색으로 반환됩니다.


1
??연산자를 잘 사용하면 편의 솔루션을 가져 왔지만 기본값으로 확장하면 데이터가 불안정하거나 예기치 않은 동작이 발생할 수 있습니다. 그것은 구체적인 서브 클래스 Dictionary가 채택해야 할 것 같습니다 . nil상황 별 기능을 제외한 반품의 경우 첫 번째 값이 얼마나 자주 필요 합니까?
NoodleOfDeath


0

선택적 NSAttributedString을 저장하는 캐시 구현에 대한 내 솔루션 :

public static var attributedMessageTextCache    = [String: NSAttributedString?]()

    if attributedMessageTextCache.index(forKey: "key") != nil
    {
        if let attributedMessageText = TextChatCache.attributedMessageTextCache["key"]
        {
            return attributedMessageText
        }
        return nil
    }

    TextChatCache.attributedMessageTextCache["key"] = .some(.none)
    return nil

0

Swift 3에서 나를 위해 작동하는 것은 다음과 같습니다.

let _ = (dict[key].map { $0 as? String } ?? "")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.