3

ある程度のストレスの後、次の汎用関数を作成しました。

func removeDupes<T : Hashable > (inout inputCollection : [T] ) -> [T] {
  var hashMap = [T : Bool]()
  var output = 0
  for thing in inputCollection {
    if !hashMap[thing] {
      hashMap[thing] = true
      inputCollection[output++] = thing
    }
  }
  while (inputCollection.count > output) {
    inputCollection.removeLast()
  }
  return inputCollection
}

だからあなたがするとき:

var names = ["Bob", "Carol", "Bob", "Bob", "Carol", "Ted", "Ted", "Alice", "Ted", "Alice"]
removeDupes(&names)

名前には次が含まれます: ["ボブ"、"キャロル"、"テッド"、"アリス"]

ここで、Array の拡張メソッドとして "removeDupes" を一般的に追加したいと思います。Hashable アイテムの配列になるように制約する必要があるため、構文に悩まされています。

次のように宣言できることを望んでいました。

extension Array {
  func removeDupes< T : Hashable> () -> [T] {
    return removeDupes(&self)
  }
}

しかし、私はエラーが発生します:

配列は '@lvalue inout $T5' に変換できません

答えは「バカ野郎、こうしろ」か「無理だ」のどちらかだと思います。

どちらになりますか?:-D

4

4 に答える 4

3

Arrayクラスは次のように宣言されます。

public struct Array<Element>

Swift 2.0 以降、ジェネリックパラメータがプロトコルに準拠しているインスタンスに対してのみ拡張メソッドを作成できます。Element

extension Array where Element: Hashable {
    @warn_unused_result
    func removeDupes() -> [Element] {
        var hashMap = [Element : Bool]()
        var result = [Element]()

        for thing in self {
            if hashMap[thing] == nil {
                hashMap[thing] = true
                result.append(thing)
            }
        }
        return result
    }
}

where拡張宣言のステートメントに注意してください。このように、removeDupesメソッドはHashable要素の配列に対してのみ宣言されます。

let names = ["Bob", "Carol", "Bob", "Bob", "Carol", "Ted", "Ted", "Alice", "Ted", "Alice"]
let uniqueNames = names.removeDupes()   // returns ["Bob", "Carol", "Ted", "Alice"]
于 2016-07-26T09:02:14.287 に答える
2

配列は として定義されArray<T>ます。つまり、配列は任意の型 T を保持でき、T は必ずしもHashableプロトコルに準拠しているわけではありません。したがって、この制約を必要とするメソッドを適用することはできません。残念ながら、属性Hashable で宣言されていない@objcため、このプロトコルに対してチェックまたはダウンキャストすることもできません。

Dictionary を使用して重複を削除することは可能ですが、上記と同じ理由でキーに T を使用することはできません。ただし、T が文字列として一意に表現できる場合、これは機能するはずです。

extension Array {
    func unique()->Array<T> {
        var buffer = Dictionary<String,T>()
        for it in self {
            buffer["\(it)"] = it
        }
        return Array(buffer.values)
    } 
}
于 2014-07-23T00:31:15.477 に答える