2015-04-21 14 views
5

Tôi đang cố gắng xây dựng một hàm nhanh chóng sẽ ánh xạ một mảng, chia từng giá trị trong mảng bằng 3, sau đó nhổ ra một mảng mới. Đây là những gì tôi có cho đến nay:Làm cách nào để định dạng đúng chức năng Swift này để ánh xạ một mảng?

func divideby3Map<T, U>(y: [T], z: T -> U) -> [U] { 

     let array = [int]() 
     let divideby3Array = array.map { [y]/3 } 

     return dividedby3Array 
    } 

    divideby3Map([1,2,3,4,5]) 

đâu TU là những mảng ban đầu, và các mảng mới được trả lại tương ứng, và nó được thực hiện sử dụng Generics.

Tôi chắc chắn điều này không được viết đúng cách, tôi bị mắc kẹt theo đúng cú pháp. Ví dụ, kể từ khi mảng được trả về được đại diện bởi các chung chung [U], tôi giả sử tôi phải sử dụng nó một nơi nào đó trong mảng đang được trả lại, không chắc chắn nơi mặc dù.

+0

Nếu nó chỉ là toán học tại sao bạn không chỉ cần sử dụng Int hoặc tăng gấp đôi? –

Trả lời

7

Khi viết chức năng chung, đôi khi dễ dàng tiếp cận nó theo 3 bước: trước tiên hãy viết mã độc lập bằng cách sử dụng một loại cụ thể. Sau đó viết mã như một hàm, vẫn còn với một kiểu cụ thể. Cuối cùng, thay đổi hàm thành generic.

Phần thứ nhất, chia một mảng 3, có thể được thực hiện như thế này:

let a = [1,2,3,4,5] 
// map is run on the array of integers, and returns a new 
// array with the operation performed on each element in a: 
let b = a.map { $0/3 } 
// so b will be [0,0,1,1,1] 
// (don’t forget, integer division truncates) 

Lưu ý việc đóng cửa mà bạn cung cấp giữa { } là một hoạt động mà sẽ được áp dụng cho từng yếu tố của mảng . $0 đại diện cho phần tử, và bạn chia nó cho 3. Bạn cũng có thể viết nó như là a.map { i in i/3 }.

Để đưa điều này vào chức năng riêng của nó:

func divideby3Map(source: [Int]) -> [Int] { 
    return source.map { $0/3 } 
} 

Không cần phải khai báo một mảng tươi - map sẽ tạo cho bạn. Sau đó, bạn có thể trả lại trực tiếp (bạn có thể gán nó tạm thời nếu bạn thích, nhưng điều đó không thực sự cần thiết).

Cuối cùng, nếu bạn muốn làm cho nó chung chung, hãy bắt đầu bằng cách thêm một giữ chỗ:

func divideby3Map<T>(source: [T]) -> [T] { 
    return source.map { $0/3 } 
} 

Lưu ý, chỉ có một nhu cầu cho một placeholder, T, bởi vì bạn đang quay trở lại cùng loại chính xác mà bạn được thông qua in.

Ngoại trừ ... điều này sẽ không biên dịch, vì trình biên dịch không biết rằng T được đảm bảo cung cấp hai điều quan trọng: khả năng phân chia (toán tử /) và khả năng tạo mới T từ số nguyên literals (tức là để tạo ra một T với giá trị 3 để chia cho). Nếu không, điều gì sẽ xảy ra nếu chúng ta truyền một mảng các chuỗi hoặc một mảng các mảng?

Để thực hiện việc này, chúng tôi cần "hạn chế" T để chức năng của chúng tôi chỉ chấp nhận làm loại đối số cung cấp các tính năng này. Một trong những giao thức chúng ta có thể sử dụng để hạn chế TIntegerType, mà không đảm bảo các tính năng này (cũng như một số những người khác như +, * vv):

func divideby3Map<T: IntegerType>(source: [T]) -> [T] { 
    return source.map { $0/3 } 
} 

divideby3Map(a) // returns [0,0,1,1,1] 

let smallInts: [UInt8] = [3,6,9] 
divideby3Map(smallInts) // returns [1,2,3] 
Các vấn đề liên quan