How to a Convert a Dictionary Slice to a Dictionary in Swift

How to a convert a Dictionary Slice to a Dictionary in Swift

There's no such thing as a DictionarySlice like there is ArraySlice. Instead, dropFirst() returns a Slice<Dictionary> which doesn't support key subscripting like Dictionary does. However, you can loop through a Slice<Dictionary> with key-value pairs just like you can with Dictionary:

let dictionary = ["a": 1, "b": 2, "c": 3]

var smallerDictionary: [String: Int] = [:]

for (key, value) in dictionary.dropFirst() {
smallerDictionary[key] = value
}

print(smallerDictionary) // ["a": 1, "c": 3]

An extension would make this a bit more elegant:

extension Dictionary {

init(_ slice: Slice<Dictionary>) {
self = [:]

for (key, value) in slice {
self[key] = value
}
}

}

let dictionary = ["a": 1, "b": 2, "c": 3]
let smallerDictionary = Dictionary(dictionary.dropFirst())
print(smallerDictionary) // ["a": 1, "c": 3]

I wouldn't really recommend doing this, though, because

  • you don't know which key-value pair will be dropped, and
  • it's not truly random either.

But if you really want to do this, now you know how to do it.

Swift 3: Array to Dictionary?

I think you're looking for something like this:

extension Array {
public func toDictionary<Key: Hashable>(with selectKey: (Element) -> Key) -> [Key:Element] {
var dict = [Key:Element]()
for element in self {
dict[selectKey(element)] = element
}
return dict
}
}

You can now do:

struct Person {
var name: String
var surname: String
var identifier: String
}

let arr = [Person(name: "John", surname: "Doe", identifier: "JOD"),
Person(name: "Jane", surname: "Doe", identifier: "JAD")]
let dict = arr.toDictionary { $0.identifier }

print(dict) // Result: ["JAD": Person(name: "Jane", surname: "Doe", identifier: "JAD"), "JOD": Person(name: "John", surname: "Doe", identifier: "JOD")]

If you'd like your code to be more general, you could even add this extension on Sequence instead of Array:

extension Sequence {
public func toDictionary<Key: Hashable>(with selectKey: (Iterator.Element) -> Key) -> [Key:Iterator.Element] {
var dict: [Key:Iterator.Element] = [:]
for element in self {
dict[selectKey(element)] = element
}
return dict
}
}

Do note, that this causes the Sequence to be iterated over and could have side effects in some cases.

How to grab a Dictionary and convert it to a list of strings from another function?

You can pull the keys into an array in multiple ways:

let newArray = Array(snapshot.keys.map{ $0 })

You can also combine them both

let array = snapshot.keys.array.map { "\($0) \(snapshot[$0]!)" }

How to create a dictionary of which the value is @State?

Quick work around to get this working: manually create the binding:



Toggle(isOn: .init(
get: { flags[name] ?? false },
set: { flags[name] = $0 }
)) {
// ...
}

I'm looking into it why $flags[name]doesn't result in a Binding. It might be related to dictionary[key] returning an optional<value> instead of the value directly.

Another hypothesis is, in Swift, that brackets are mostly syntax sugar to call the subscript function. A function cannot be bound to, as it's only read only and bindings need write access to modify the value. This also explains why you can't bind to an array element, but I'm not 100% sure on either answer and would be happy to edit this in favor of the community

How to reference element from [NSObject : AnyObject] Swift dictionary after bridging from NSDictionary

Probably not the most elegant approach, but this worked:

    let castedVideoDict = videoDict as! Dictionary<String, NSObject>        
let filePath = castedVideoDict["PBJVisionVideoPathKey"] as! String

Cannot convert value of type '(key: String, value: AnyObject)' to expected argument type '[String : AnyObject]'

  • First of all classes are supposed to be named in singular form Post / ThumbImage. The datasource array e.g. posts contains Post instances and each Post instance contains an array thumbnailImages of ThumbImage instances. These semantics make it easier to understand the design.
  • Second of all JSON dictionaries in Swift 3+ are [String:Any]
  • Third of all according to the initialization rules the super call must be performed after initializing all stored properties.

The value of key thumbnail_images is a dictionary containing dictionaries. The error occurs because you are using the array enumeration syntax which treats the dictionary as an array of tuples.

The dictionary can be parsed to use the key as size name and the value to pass the parameters.

I have no idea why you are using NSObject subclasses but I'm sure you have your reasons.


This is the Thumbnail class

class ThumbImage: NSObject {

let size: String
var url : URL?
let width : Int
let height : Int

init(size : String, parameters: [String: Any]) {

self.size = size
if let urlString = parameters["url"] as? String {
self.url = URL(string: urlString)
}
self.width = parameters["width"] as? Int ?? 0
self.height = parameters["height"] as? Int ?? 0
super.init()
}
}

and this the Post class

class Post: NSObject {

var title: String
var excerpt: String
var content: String
var thumbnailImages = [ThumbImage]()

init(dict: [String: Any])
{
self.title = dict["title"] as? String ?? ""
self.excerpt = dict["excerpt"] as? String ?? ""
self.content = dict["content"] as? String ?? ""
super.init()
if let images = dict["thumbnail_images"] as? [String: [String:Any] ] {
for (key, value) in images {
thumbnailImages.append(ThumbImage(size: key, parameters: value))
}
}
}
}


Related Topics



Leave a reply



Submit