2016-07-19 22 views
12

Tôi có một mảng các đối tượng Person 's:Map mảng các đối tượng vào từ điển trong Swift

class Person { 
    let name:String 
    let position:Int 
} 

và mảng là:

let myArray = [p1,p1,p3] 

Tôi muốn để lập bản đồ myArray là một từ điển của [position:name] giải pháp cổ điển là:

var myDictionary = [Int:String]() 

for person in myArray { 
    myDictionary[person.position] = person.name 
} 

có cách nào thanh lịch b y Swift để làm điều đó với cách tiếp cận chức năng map, flatMap ... hay phong cách Swift hiện đại khác

+0

cách cổ điển của bạn là tốt hơn nhiều trong hoạt động – AamirR

Trả lời

28

Okay map không phải là một ví dụ tốt về điều này, bởi vì nó chỉ giống như vòng lặp, bạn có thể u se reduce thay vào đó, mỗi đối tượng của bạn phải kết hợp và biến thành một giá trị duy nhất:

let myDictionary = myArray.reduce([Int: String]()) { (dict, person) -> [Int: String] in 
    var dict = dict 
    dict[person.position] = person.name 
    return dict 
} 

//[2: "b", 3: "c", 1: "a"] 
+0

Đây là phương pháp tôi đã nghĩ đến việc. – Fogmeister

+1

Tôi thích cách tiếp cận này nhưng điều này hiệu quả hơn chỉ đơn giản là tạo vòng lặp để tải từ điển? Tôi lo lắng về hiệu suất bởi vì nó có vẻ như đối với mỗi mục nó phải tạo ra một bản sao mới có thể thay đổi của một từ điển lớn hơn bao giờ hết ... –

+0

nó thực sự là một vòng lặp, cách này là cách đơn giản để viết nó, hiệu suất là như nhau hoặc bằng cách nào đó tốt hơn hơn bình thường vòng lặp – Tj3n

4

Bạn có thể viết initializer tùy chỉnh cho Dictionary loại, ví dụ từ các bộ:

extension Dictionary { 
    public init(keyValuePairs: [(Key, Value)]) { 
     self.init() 
     for pair in keyValuePairs { 
      self[pair.0] = pair.1 
     } 
    } 
} 

và sau đó sử dụng map cho mảng lại Person:

var myDictionary = Dictionary(keyValuePairs: myArray.map{($0.position, $0.name)}) 
1

Bạn có thể sử dụng chức năng giảm. Đầu tiên tôi đã tạo ra một initializer dành riêng cho Person lớp

class Person { 
    var name:String 
    var position:Int 

    init(_ n: String,_ p: Int) { 
    name = n 
    position = p 
    } 
} 

Sau đó, tôi đã khởi tạo một mảng các giá trị

let myArray = [Person("Bill",1), 
       Person("Steve", 2), 
       Person("Woz", 3)] 

Và cuối cùng, biến điển có kết quả:

let dictionary = myArray.reduce([Int: Person]()){ 
    (total, person) in 
    var totalMutable = total 
    totalMutable.updateValue(person, forKey: total.count) 
    return totalMutable 
} 
15

Trong Swift 4 bạn có thể làm cách tiếp cận @ Tj3n sạch hơn và hiệu quả hơn bằng cách sử dụng phiên bản into của reduce Nó loại bỏ các dictio tạm thời nary và giá trị trả về vì vậy nó nhanh hơn và dễ đọc hơn.

struct Person { 
    let name: String 
    let position: Int 
} 
let myArray = [Person(name:"h", position: 0), Person(name:"b", position:4), Person(name:"c", position:2)] 
let myDict = myArray.reduce(into: [Int: String]()) { 
    $0[$1.position] = $1.name 
} 
print(myDict) 

Lưu ý: Không làm việc trong Swift 3.

Các vấn đề liên quan