programing

Swift로 입력된 어레이를 확장하려면 어떻게 해야 합니까?

starjava 2023. 4. 22. 08:22
반응형

Swift로 입력된 어레이를 확장하려면 어떻게 해야 합니까?

하면 's 할 수 있을까요?Array<T> ★★★★★★★★★★★★★★★★★」T[]스텀 기기 틸틸 틸틸 틸??

Swift의는 Swift API의 을 알 수 .T[] 예: 개요:

extension T[] : ArrayType {
    //...
    init()

    var count: Int { get }

    var capacity: Int { get }

    var isEmpty: Bool { get }

    func copy() -> T[]
}

같은 소스를 복사 및 붙여넣고 다음과 같은 변형을 시도할 경우:

extension T[] : ArrayType {
    func foo(){}
}

extension T[] {
    func foo(){}
}

다음 오류로 인해 빌드할 수 없습니다.

타입 「」T[]할 수

하면 에러가 .Use of undefined type 'T' (예:)

extension Array<T> {
    func foo(){}
}

또 .Array<T : Any> ★★★★★★★★★★★★★★★★★」Array<String>.

이상하게도 Swift는 다음과 같은 기능을 사용하여 비타이프형 어레이를 확장할 수 있습니다.

extension Array {
    func each(fn: (Any) -> ()) {
        for i in self {
            fn(i)
        }
    }
}

전화할 수 있게 해주지

[1,2,3].each(println)

그러나 Swift의 빌트인 필터를 다음과 같이 바꾸려고 하면 메서드를 통과할 때 유형이 손실되는 것처럼 보이기 때문에 적절한 범용 유형 확장을 만들 수 없습니다.

extension Array {
    func find<T>(fn: (T) -> Bool) -> T[] {
        var to = T[]()
        for x in self {
            let t = x as T
            if fn(t) {
                to += t
            }
        }
        return to
    }
}

그러나 컴파일러는 다음과 같은 방법으로 내선번호를 호출할 수 있는 경우 해당 내선번호를 입력되지 않은 것으로 간주합니다.

["A","B","C"].find { $0 > "A" }

steped-thru가 을 나타냅니다.Swift.StringString 번째, "syslog", "syslog:

["A","B","C"].find { ($0 as String).compare("A") > 0 }

내장된 확장자처럼 작동하는 올바른 확장자 방법을 아는 사람이 있습니까?

클래스로 타입 어레이를 확장하는 경우는, 이하와 같이 대응합니다(Swift 2.2).예를 들어, 유형 배열 정렬:

class HighScoreEntry {
    let score:Int
}

extension Array where Element == HighScoreEntry {
    func sort() -> [HighScoreEntry] {
      return sort { $0.score < $1.score }
    }
}

구조체 또는 타입에일리어스를 사용하여 이 작업을 수행하려고 하면 다음과 같은 오류가 발생합니다.

Type 'Element' constrained to a non-protocol type 'HighScoreEntry'

업데이트:

클래스가 아닌 유형 어레이를 확장하려면 다음 방법을 사용합니다.

typealias HighScoreEntry = (Int)

extension SequenceType where Generator.Element == HighScoreEntry {
    func sort() -> [HighScoreEntry] {
      return sort { $0 < $1 }
    }
}

Swift 3에서는 일부 유형의 이름이 변경되었습니다.

extension Sequence where Iterator.Element == HighScoreEntry 
{
    // ...
}

.<T>뭇매를 맞다

extension Array {
    func find(fn: (T) -> Bool) -> [T] {
        var to = [T]()
        for x in self {
            let t = x as T;
            if fn(t) {
                to += t
            }
        }
        return to
    }
}

이제 빌드 오류 없이 의도한 대로 작동합니다.

["A","B","C"].find { $0.compare("A") > 0 }

모든 유형 확장:

extension Array where Element: Any {
    // ...
}

비교 가능한 유형 확장:

extension Array where Element: Comparable {
    // ...
}

일부 유형 확장:

extension Array where Element: Comparable & Hashable {
    // ...
}

특정 유형을 확장합니다.

extension Array where Element == Int {
    // ...
}

swap() 메서드를 사용하여 일반적인 어레이를 확장하려고 했는데, 어레이와 같은 유형의 인수를 사용해야 했습니다.하지만 범용 타입은 어떻게 지정하나요?시행착오를 통해 아래가 효과가 있음을 알게 되었습니다.

extension Array {
    mutating func swap(x:[Element]) {
        self.removeAll()
        self.appendContentsOf(x)
    }
}

그것의 열쇠는 '요소'라는 단어였다.이 유형은 정의하지 않았습니다.이 유형은 어레이 확장 컨텍스트 내에 자동으로 존재하며 어레이 요소의 유형이 무엇이든 참조할 수 있습니다.

여기서 무슨 일이 일어나고 있는지 100% 알 수 없지만, 아마도 'Element'가 어레이의 관련 유형이기 때문일 것입니다(https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID189의 'Associated Types).

다만, 어레이 구조 레퍼런스(https://developer.apple.com/library/prerelease/ios/documentation/Swift/Reference/Swift_Array_Structure/index.html #//apple_ref/swift/struct/s:Sa)에는 이 레퍼런스를 찾을 수 없기 때문에 아직 잘 모르겠습니다.

Swift 2.2 사용: 문자열 배열에서 중복을 제거하려고 할 때 유사한 문제가 발생했습니다.원하는 대로 Array 클래스에 확장을 추가할 수 있었습니다.

extension Array where Element: Hashable {
    /**
     * Remove duplicate elements from an array
     *
     * - returns: A new array without duplicates
     */
    func removeDuplicates() -> [Element] {
        var result: [Element] = []
        for value in self {
            if !result.contains(value) {
                result.append(value)
            }
        }
        return result
    }

    /**
     * Remove duplicate elements from an array
     */
    mutating func removeDuplicatesInPlace() {
        var result: [Element] = []
        for value in self {
            if !result.contains(value) {
                result.append(value)
            }
        }
        self = result
    }
}

이 두 가지 메서드를 Array 클래스에 추가하면 어레이의 두 메서드 중 하나를 호출하여 중복된 메서드를 제거할 수 있습니다.배열의 요소는 해시 가능 프로토콜을 준수해야 합니다.이제 할 수 있습니다.

 var dupes = ["one", "two", "two", "three"]
 let deDuped = dupes.removeDuplicates()
 dupes.removeDuplicatesInPlace()
 // result: ["one", "two", "three"]

어레이 및 기타 유형의 빌트인 클래스 확장에 대한 자세한 내용은 이 github repo에서 확인 코드를 참조하십시오.https://github.com/ankurp/Cent

Xcode 6.1에서 어레이를 확장하는 구문은 다음과 같습니다.

extension Array {
    func at(indexes: Int...) -> [Element] {
        ... // You code goes herer
    }
}

Swift 2의 표준 라이브러리 헤더를 봤는데, 여기 필터 기능의 프로토타입이 있습니다.필터 기능의 프로토타입은, 자신의 것을 롤 하는 방법을 알 수 있습니다.

extension CollectionType {
    func filter(@noescape includeElement: (Self.Generator.Element) -> Bool) -> [Self.Generator.Element]
}

어레이의 확장이 아니라 컬렉션의 확장입니다.[Type] : 다른 컬렉션타입에도 같은 방법이 적용됩니다.@noescape는 전달된 블록이 필터 기능의 범위를 벗어나지 않음을 의미하며, 이는 일부 최적화를 가능하게 됩니다.대문자 S를 가진 Self가 우리가 확장하고 있는 클래스입니다.Self.Generator는 컬렉션과 Self의 오브젝트를 반복하는 반복기입니다.발전기요소는 객체 유형입니다(예: 배열 [Int?]).Self.Generator.요소는 Int가 됩니다.

이 필터 메서드는 모든 컬렉션에 적용할 수 있습니다.유형: 컬렉션의 요소를 가져와서 Bool을 반환하고 원래 유형의 배열을 반환하는 필터 블록이 필요합니다.이를 종합하면 다음과 같은 방법이 도움이 됩니다.수집 요소를 옵션 값에 매핑하는 블록을 사용하여 맵과 필터를 결합하고 0이 아닌 옵션 값의 배열을 반환합니다.

extension CollectionType {

    func mapfilter<T>(@noescape transform: (Self.Generator.Element) -> T?) -> [T] {
        var result: [T] = []
        for x in self {
            if let t = transform (x) {
                result.append (t)
            }
        }
        return result
    }
}
import Foundation

extension Array {
    var randomItem: Element? {
        let idx = Int(arc4random_uniform(UInt32(self.count)))
        return self.isEmpty ? nil : self[idx]
    }
}

(스위프트 2.x)

에 맞게 를 확장할 수도 있습니다들어 protocol " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ----- " " " " " " 。 " 。 " " " " " " " " " " " " " " " " " " 。 " " " 。 " " " " " " " " " " " " " " " " " " " " 。 " " " " " " " " " " "MyTypes이 접근방식을 사용하는 보너스는 일반적인 어레이 인수를 사용하여 함수를 쓸 수 있다는 것입니다.이러한 어레이 인수는 커스텀 함수 유틸리티 프로토콜(예를 들어 protocol)에 준거해야 합니다.MyFunctionalUtils.

이 동작은 어레이 요소를 다음과 같이 제한하여 암묵적으로 실행할 수 있습니다.MyTypes또는---아래에서 설명하는 방법으로 나타내듯이--- 범용 어레이 함수 헤더가 입력 어레이가 다음을 준수하고 있음을 직접 나타내도록 합니다.MyFunctionalUtils.


먼저 프로토콜부터 시작합니다.MyTypes유형 제약으로 사용; 제네릭에 적합할 유형을 이 프로토콜로 확장합니다(아래 참조). 기본 유형을 확장합니다).Int그리고.Double커스텀 타입과 함께MyCustomType)

/* Used as type constraint for Generator.Element */
protocol MyTypes {
    var intValue: Int { get }
    init(_ value: Int)
    func *(lhs: Self, rhs: Self) -> Self
    func +=(inout lhs: Self, rhs: Self)
}

extension Int : MyTypes { var intValue: Int { return self } }
extension Double : MyTypes { var intValue: Int { return Int(self) } }
    // ...

/* Custom type conforming to MyTypes type constraint */
struct MyCustomType : MyTypes {
    var myInt : Int? = 0
    var intValue: Int {
        return myInt ?? 0
    }

    init(_ value: Int) {
        myInt = value
    }
}

func *(lhs: MyCustomType, rhs: MyCustomType) -> MyCustomType {
    return MyCustomType(lhs.intValue * rhs.intValue)
}

func +=(inout lhs: MyCustomType, rhs: MyCustomType) {
    lhs.myInt = (lhs.myInt ?? 0) + (rhs.myInt ?? 0)
}

프로토콜MyFunctionalUtils(델의 기타 범용 어레이 기능 유틸리티의 설계도 유지) 그 후 어레이 확장:MyFunctionalUtils; 청사진 방식의 구현:

/* Protocol holding our function utilities, to be used as extension 
   o Array: blueprints for utility methods where Generator.Element 
   is constrained to MyTypes */
protocol MyFunctionalUtils {
    func foo<T: MyTypes>(a: [T]) -> Int?
        // ...
}

/* Extend array by protocol MyFunctionalUtils and implement blue-prints 
   therein for conformance */
extension Array : MyFunctionalUtils {
    func foo<T: MyTypes>(a: [T]) -> Int? {
        /* [T] is Self? proceed, otherwise return nil */
        if let b = self.first {
            if b is T && self.count == a.count {
                var myMultSum: T = T(0)

                for (i, sElem) in self.enumerate() {
                    myMultSum += (sElem as! T) * a[i]
                }
                return myMultSum.intValue
            }
        }
        return nil
    }
}

마지막으로, 테스트와 2개의 예에서는, 범용 어레이를 사용하는 함수를 나타내고 있습니다.각각 다음과 같은 경우가 있습니다.

  1. 어레이 요소를 'MyTypes'(함수)로 제한하는 형식을 통해 어레이 매개 변수가 프로토콜 'MyFunctionalUtils'를 준수한다는 암묵적 어설션 표시bar1).

  2. 배열 매개 변수가 프로토콜 'MyFunctionalUtils'(함수)를 준수함을 명시합니다.bar2).

테스트와 예는 다음과 같습니다.

/* Tests & examples */
let arr1d : [Double] = [1.0, 2.0, 3.0]
let arr2d : [Double] = [-3.0, -2.0, 1.0]

let arr1my : [MyCustomType] = [MyCustomType(1), MyCustomType(2), MyCustomType(3)]
let arr2my : [MyCustomType] = [MyCustomType(-3), MyCustomType(-2), MyCustomType(1)]

    /* constrain array elements to MyTypes, hence _implicitly_ constraining
       array parameters to protocol MyFunctionalUtils. However, this
       conformance is not apparent just by looking at the function signature... */
func bar1<U: MyTypes> (arr1: [U], _ arr2: [U]) -> Int? {
    return arr1.foo(arr2)
}
let myInt1d = bar1(arr1d, arr2d) // -4, OK
let myInt1my = bar1(arr1my, arr2my) // -4, OK

    /* constrain the array itself to protocol MyFunctionalUtils; here, we
       see directly in the function signature that conformance to
       MyFunctionalUtils is given for valid array parameters */
func bar2<T: MyTypes, U: protocol<MyFunctionalUtils, _ArrayType> where U.Generator.Element == T> (arr1: U, _ arr2: U) -> Int? {

    // OK, type U behaves as array type with elements T (=MyTypes)
    var a = arr1
    var b = arr2
    a.append(T(2)) // add 2*7 to multsum
    b.append(T(7))

    return a.foo(Array(b))
        /* Ok! */
}
let myInt2d = bar2(arr1d, arr2d) // 10, OK
let myInt2my = bar2(arr1my, arr2my) // 10, OK
import Foundation

extension Array {

    func calculateMean() -> Double {
        // is this an array of Doubles?
        if self.first is Double {
            // cast from "generic" array to typed array of Doubles
            let doubleArray = self.map { $0 as! Double }

            // use Swift "reduce" function to add all values together
            let total = doubleArray.reduce(0.0, combine: {$0 + $1})

            let meanAvg = total / Double(self.count)
            return meanAvg

        } else {
            return Double.NaN
        }
    }

    func calculateMedian() -> Double {
        // is this an array of Doubles?
        if self.first is Double {
            // cast from "generic" array to typed array of Doubles
            var doubleArray = self.map { $0 as! Double }

            // sort the array
            doubleArray.sort( {$0 < $1} )

            var medianAvg : Double
            if doubleArray.count % 2 == 0 {
                // if even number of elements - then mean average the middle two elements
                var halfway = doubleArray.count / 2
                medianAvg = (doubleArray[halfway] + doubleArray[halfway - 1]) / 2

            } else {
                // odd number of elements - then just use the middle element
                medianAvg = doubleArray[doubleArray.count  / 2 ]
            }
            return medianAvg
        } else {
            return Double.NaN
        }

    }

}

확장 배열 검색 색인:

extension Array where Element: Equatable {
func findElementArrayIndex1(findElement: String) -> Int {
    var indexValue: Int = -1
    var search = filter { findElement.isEmpty || "\($0)".contains(findElement) }
    // print("search: \(search)")
    if search.count > 0
    {
        for i in 0 ..< count {
            if self[i] == search[0] {
                indexValue = i
                break
            }
        }
    }
    //print("indexValue -- : \(indexValue)")
    return indexValue
}}

언급URL : https://stackoverflow.com/questions/24027116/how-can-i-extend-typed-arrays-in-swift

반응형