2016-08-07 4 views
1

이 확장을 SequenceType에 작성하여 Python's collections.Counter과 유사하게했습니다.이 코드가 모호한 이유는 무엇입니까?

extension SequenceType where Self.Generator.Element : Hashable { 
    func countRepetitions() -> [Self.Generator.Element : Int] { 
     return self.reduce([Self.Generator.Element : Int]()) { dict, element in 
      dict[key: element] = (dict[element] ?? 0) + 1 
     } 
    } 
} 

나는 다음과 같은 오류가 발생합니다 : :

let input = [ 
    "a", "a", "a", "a", "a", 
    "b", "b", "b", "b", 
    "c", "c", "c", 
    "d", "d", 
    "e" 
] 


let counts = input.countRepetitions() 

print(counts) //expected result: ["a": 5 , "b" : 4, "c" : 3, "d" : 2, "e" : 1] 

여기에 코드입니다

중첩 유형의 변수를 정의 할 때 제한 될 것으로 보인다
Playground execution failed: OS X.playground:26:22: error: type of expression is ambiguous without more context 
       return self.reduce([Self.Generator.Element : Int]()) { dict, element in 
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

답변

6

.

let foo1: [Self.Generator.Element : Int] = [:] 

이 방법 안에 컴파일 동안, 이것은하지 않습니다 : 귀하의 경우에

typealias E = Self.Generator.Element 
let foo3 = [E : Int]() 

를 적용 :

해결 방법으로
let foo2 = [Self.Generator.Element : Int]() 
// error: type of expression is ambiguous without more context 

, 당신은 typealias를 정의 할 수 있습니다

extension SequenceType where Self.Generator.Element : Hashable { 
    func countRepetitions() -> [Self.Generator.Element : Int] { 
     typealias E = Self.Generator.Element 
     return self.reduce([E : Int]()) { (dict, element) -> [E : Int] in 
      var dict = dict 
      dict[element] = (dict[element] ?? 0) + 1 
      return dict 
     } 
    } 
} 

(클로저 매개 변수 eters가 상수 인 경우이므로 을 먼저 변경 가능한 복사본으로 만들어야합니다. . 또한 폐쇄)

을 값을 반환해야하지만 실제로는 문제를 방지 할 수 있고 컴파일러가 타입 추론하자 : 또한 reduce 각 반복 단계에서 새 사전을 생성

extension SequenceType where Self.Generator.Element : Hashable { 
    func countRepetitions() -> [Self.Generator.Element : Int] { 
     return self.reduce([:]) { (dict, element) in 
      var dict = dict 
      dict[element] = (dict[element] ?? 0) + 1 
      return dict 
     } 
    } 
} 

주 . 보다 효율적인 솔루션이 나는 또한 (중복) Self.를 생략 한

extension SequenceType where Generator.Element : Hashable { 
    func countRepetitions() -> [Generator.Element : Int] { 
     var dict: [Generator.Element: Int] = [:] 
     self.forEach { 
      dict[$0] = (dict[$0] ?? 0) + 1 
     } 
     return dict 
    } 
} 

될 것이다.

+0

흥미 롭습니다. 그 제한이 존재하는 이유를 알고 있습니까? 그리고 두 번째 부분에서 언급 한 오류를 용서해주십시오. 컴파일러가 아직 xD를 검사하지 않았습니다. – Alexander

+0

@AlexanderMomchliov : 불행히도 이유를 모르겠습니다. –

+0

그건 그렇고, 새로운 매핑을 포함하는 사전 사본을 모두 한 표현으로 반환하는 방법을 알고 있습니까? 'return array + [newItem]'에 해당하는 사전 – Alexander