2017-01-07 18 views
9

Lắp ráp một tải trọng dữ liệu được chuyển đến GRMustache.swift để hiển thị mẫu ria mép, tôi đang ở trong trường hợp cần thêm dữ liệu vào mảng được xác định trước đó trong từ điển.Nối vào mảng trong cấu trúc từ điển [String: Any]

cấu trúc dữ liệu của tôi bắt đầu giảm giá như:

var data: [String: Any] = [ 
    "key1": "example value 1", 
    "key2": "example value 2", 
    "items": [ 
     // I need to append here later 
    ] 
] 

Các items cặp khóa là một bộ sưu tập Tôi cần phải thêm sau trong vòng một vòng lặp.

Để thêm vào các mảng data["items"], tôi đang cố gắng một cái gì đó như:

for index in 1...3 { 
    let item: [String: Any] = [ 
     "key": "new value" 
    ] 

    data["items"].append(item) 
} 

lỗi này, như giá trị của loại Any? không có thành viên append, và điều hành nhị phân += không thể được áp dụng cho toán hạng kiểu Any?[String : Any].

Điều này có ý nghĩa, vì tôi cần truyền giá trị để nối thêm; tuy nhiên, tôi không thể thay đổi mảng.

Đúc đến mảng, cho dù buộc nhìn xuống cung cấp cho các lỗi:

(data["items"] as! Array).append(item) 

'Any?' is not convertible to 'Array<_>'; did you mean to use 'as!' to force downcast?

Cannot use mutating member on immutable value of type 'Array<_>'

Có vẻ như dàn diễn viên của tôi là sai; hoặc, có lẽ tôi đang đi về điều này một cách sai lầm.

Bất kỳ đề xuất nào về cách điền data["items"] lặp đi lặp lại theo thời gian?

Trả lời

6

Loại data[Items] không phải là Array nhưng thực tế là Array<[String: Any]>.

Bạn có thể có thể bóp này thành những bước ít hơn, nhưng tôi thích sự rõ ràng của nhiều bước:

var data: [String: Any] = [ 
    "key1": "example value 1", 
    "key2": "example value 2", 
    "items": [] 
] 

for index in 1...3 { 

    let item: [String: Any] = [ 
     "key": "new value" 
    ] 

    // get existing items, or create new array if doesn't exist 
    var existingItems = data["items"] as? [[String: Any]] ?? [[String: Any]]() 

    // append the item 
    existingItems.append(item) 

    // replace back into `data` 
    data["items"] = existingItems 
} 
3

subscript với Dictionary luôn luôn trả optional(?) dụ vì nó có thể có thể là key không tồn tại trong Dictionary. Bây giờ bạn đã khai báo từ điển của mình là [String:Any] có nghĩa là loại keyStringvalueAny.

Bây giờ, khi bạn viết data["item"] nó sẽ trả lại cho bạn Any? không phải là mảng để bạn không thể gọi append và nó sẽ trả lại giá trị bất biến để bạn không thể trực tiếp thay đổi nó.

Vì vậy, bạn cần phải nhập nó vào Array of Dictionary và lưu nó vào thể hiện và gắn ví dụ đó sau đó thay thế đối tượng đó trong từ điển của bạn bằng cách gán lại nó.

for index in 1...3 { 
    let item: [String: Any] = [ 
     "key": "new value" 
    ] 

    var array = data["items"] as? [[String:Any]] ?? [[String:Any]]() 
    array.append(item) 
    data["items"] = array 
} 

Bây giờ điều được nên dễ dàng hơn rất nhiều nếu bạn có Dictionary như [String: [[String:Any]]] cho ví dụ.

var data: [String: [[String:Any]]] = [ 
    "items": [] 
] 

for index in 1...3 { 
    let item: [String: Any] = [ 
     "key": "new value" 
    ] 
    data["items"]?.append(item) 
} 
+0

@JasonSturges Tôi biết, tôi đã chỉ cho bạn thấy vấn đề là gì và ở đâu bạn có thể trực tiếp nối thêm mảng nằm trong từ điển. –

+1

Thực sự đánh giá cao sự rõ ràng và thanh lịch của kiểu gõ [[String: [[String: Any]]] '. –

+0

Lưu ý rằng bạn có thể sử dụng 'dữ liệu [" mục "] ?. chắp thêm (mục)' thay vì 'dữ liệu [" mục "] !. chắp thêm (mục)' ở trên; sau này sẽ tạo ra một sự cố thời gian chạy nếu không có giá trị nào cho khóa '" items ('ngay cả khi chúng ta biết nó nằm trong ví dụ này), trong khi cái cũ sẽ đơn giản trả về một' nil' chưa được sử dụng. Ngay cả khi chúng ta biết khóa ''mục' 'tồn tại, tôi tin rằng chúng ta nên thích cách tiếp cận an toàn hơn, đặc biệt là khi nó không có thêm chi phí. Luôn luôn là một nguy cơ tăng cường thực hành xấu '!' Cho người đọc SO mới bắt đầu mà không nhận ra rằng trong trường hợp cụ thể/ví dụ này, '!' Là an toàn, nhưng nói cách khác, nói chung là không. – dfri

3

Nếu bạn thích ngắn gọn hơn rõ ràng, bạn có thể thực hiện thao tác này trong một dòng duy nhất, làm cho việc sử dụng nil coalescing điều hành và the + operator for RangeReplaceableCollection (mà Array Tuân), sau này được sử dụng để "gắn" bước (trong thực tế, xây dựng một bộ sưu tập mới sẽ thay thế bộ sưu tập hiện tại khi thay thế giá trị data["items"]).

// example setup 
var data: [String: Any] = [ 
    "key1": "example value 1", 
    "key2": "example value 2", 
    "items": [] 
] 

// copy-mutate-replace the "items" array inline, adding a new dictionary 
data["items"] = (data["items"] as? [[String: Any]] ?? []) + [["key": "new value"]] 

print(data) 
/* ["key2": "example value 2", 
    "items": [["key": "new value"]], 
    "key1": "example value 1"]  */ 

// add another dictionary to the "items" array 
data["items"] = (data["items"] as? [[String: Any]] ?? []) + [["key": "new value"]] 

print(data) 
/* ["key2": "example value 2", 
"items": [["key": "new value"], ["key": "new value"]], 
"key1": "example value 1"]  */ 
0

Cung cấp cho bạn có một Array của items:[String]

Ông cũng có thể thêm video này vào các json

var items = ["string1", "Info 2","Text 4"] 

data["items"] = items 
Các vấn đề liên quan