check if there much id inside dictionary than holds objects - swift

I have a dictionary that holds objects, inside that objects I have an id, is there a way to check matches with this id and return the object?
example:
if I have id = 2 and I want to check if there exists in the object and get the particular object that matches with this id
Thanks for the help
my structs:
struct CoinsInfo:Codable {
let data:[String:CoinSpecificInfo]?
}
struct CoinSpecificInfo:Codable {
let urls:UrlsCoins?
let logo:String?
let id:Int?
let symbol:String?
}

You can try
// item is an instance of CoinsInfo
// get a new dictionary with all keys that has id matching in their value
guard let matches = item.data?.filter { $1.id == 2 } else { return }
// get an array of objects
let arr = Array(matches.values)

Related

How can i extract the array of the objects in Swift?

i have json objects like and parsed in an array
let objects = [Object]()
struct Object {
name: String
id: Int
}
Suppose like
let objects [Object(name:oscar, id: 11), Object(name:sanchez, id: 12),Object(name:emily, id: 15),Object(name:clarck, id: 31) ... ]
How can i take the string array as below also with this name which object belongs to ? ( so i can use object easily)
let stringPropertyArray = [oscar, sanchez,emily,clarck ... ]
Thanks
how i will find the object ? if you have "emily" and i want to item.id which emily belongs to ?
Perhaps you want something like
if let ob = objects.first {$0.name == "emily"} {
print(ob.id)
}
But if your goal is to search quickly, it would be better to have a dictionary keyed by the value you will be searching on.
I think this is what you want
let stringPropertyArray: [String] = objects.map {$0.name}
There are 2 approaches you can use:
by looping (traditional approach)
var listName: [String] = []
for item in objects {
listName.append(item.name)
}
by using higher order function
let listName = objects.map{ $0.name }
There would be a case if your name property is optional and for some object, name property value is nil then we should use compactMap higher order function in order to avoid nil object in the list
let listName = objects.compactMap{ $0.name }
To find any specific object we can use filter like below:
let object = objects.filter{
$0.name == "sanchez" }.first
// OR
let object = objects.first { object -> Bool in
object.name == "emily" }

how to read data into object array in Swift 4

class Employee{
var id:Int
var name:String
var salary:Int
init(){
self.id=0
self.name=""
self.salary=0
}
func getInfo(){
self.name=readLine()!
self.id=Int(readLine()!)!
self.salary=Int(readLine()!)!
}
}
var count=0
var flag="y"
var empData:[Employee]=[]
repeat{
count+=1
empData[count]=Employee()
empData[count].getInfo()
flag=readLine()!
}while(flag=="y") `
I have a class Employee with properties id , nam and salary. The function getInfo() is used to get information from user. I want to read data until the flag!="y" . I am getting index out of range error.
What is the right way of inputting data? Can we index the objects ?
You need to append to your array to make it increase in size. Replace
empData[count]=Employee()
with
empData.append(Employee())
to avoid index out of range error
Update
To make your code a little less horrible I would do
repeat {
var employee = Employee()
employee.getInfo()
empData.append(employee)
flag=readLine()!
}while( flag == "y" )
The subscript operator cannot be used to add elements to an array index which doesn't exist yet. You either need to initialize the array with an element count if you know at the time of initialization how many elements your array will have or use the append operator to add new elements to the array after the last index.
You don't even need the count variable, as you can simply access empData.last safely after calling append and adding a new Employee to the Array.
var flag="y"
var empData:[Employee]=[]
repeat {
empData.append(Employee())
empData.last!.getInfo()
flag=readLine()!
} while(flag=="y")
I would advise you to seriously reconsider your implementation as it is really unsafe at the moment. You are not validating user input in any way, hence your getInfo function can easily cause runtime errors if the user input is not in the expected form. Moreover, creating an empty initializer for Employee doesn't make sense, you could simply create a failable initializer, where you read the input and if the input is not of the correct form, make the initializer return nil.
class Employee{
let id:Int
let name:String
let salary:Int
init?(){
guard let name = readLine() else { return nil }
self.name = name
guard let idString = readLine(), let id = Int(idString) else { return nil }
self.id = id
guard let salaryString = readLine(), let salary = Int(salaryString) else { return nil}
self.salary = salary
}
}
var flag="y"
var empData:[Employee]=[]
repeat {
if let employee = Employee() {
empData.append(employee)
} else {
// Display error message to the user
}
flag=readLine() ?? ""
} while(flag=="y")

realm. remove objects from ListBase

I have different realm models. They have List properties. I want to make universal way for removing objects from List properties. So I did the following:
if let list = self[property.name] as? ListBase {
list._rlmArray.removeAllObjects()
}
but this just clear list property, without deleting objects from realm. The only way I've found is:
if let list = self[property.name] as? ListBase {
while list.count > 0 {
let object = list._rlmArray.firstObject()
let any = object as Any
if let theObject = any as? Object {
realm.delete(theObject)
}
}
}
Code above works and doesn't generate any warning. But it looks ugly.
You can use dynamicList(_ propertyName: String) to retrieve List property by name instead subscript.
if property.type == .array {
try! realm?.write {
realm?.delete(dynamicList(property.name))
}
}

Swift diff realm.io without fetching it in advance

I was wondering if there is a possibility in realm.io (swift) to select all items from one "table" that are not in the other one.
Lets say you have 2 classes:
class A: Object {
dynamic var id: Int = 0
dynamic var text: String = ""
}
class B: Object {
dynamic var id: Int = 0
dynamic var value: Bool = false
}
Is it possible to get an result of items from A who's id is not present in B?
There is actually a very simple way to do this using NSPredicate on Realm filter API.
func fetch() throws -> [A] {
do {
// Create Realm
let realm = try Realm()
// Get B objects from Realm and put their IDs to [Int] array
let IdB: [Int] = realm.objects(B).map { $0.id }
// Create predicate
// Filter all items where property id is not present in array IdB
let predicateFilter = NSPredicate(format: "NOT (id IN %#)", IdB)
// Get all A objects from array using predicateFilter
let objectsA = realm.objects(A).filter(predicateFilter)
// Return the [A] array
return objectsA.map { $0 }
} catch {
// Throw an error if any
throw error
}
}
Also note that all objects from fetched using Realm are lazy loaded which means that this method is also very fast. From the documentation:
All queries (including queries and property access) are lazy in Realm. Data is only read when the properties are accessed.

Swift guard else called on dictionary key with NULL value

If I have a Dictionary returned from a NSNotification containing the following
print(notificationObj.object)
Optional({
age = "<null>";
names = (
David
);
})
Then the guard else is called when trying to assign this to a variable:
guard let categories = notificationObj.object as? [String:[String]] else {
// Gets to here
return
}
How can I handle the case where a Dictionary key is null.
Your dictionary does contain ...
Optional({
age = "<null>";
names = (
David
);
})
... and ...
age = ... is String = String (value is single String),
names = ( ... ) is String = [String] (value is array of Strings).
You can't cast it to [String:[String]] because the first pair doesn't fit this type. This is the reason why your guard statement hits else.
Hard to answer your question. Dictionary contains names, you want categories, names key does contain David, which doesn't look like category, ... At least you know why guard hits else.
Your questions is not very clear.
However IF
You have a dictionary declared as follow [String:[String]]
And you want manage the scenario where a given key is not present
Like this
let devices : [String:[String]] = [
"Computers": ["iMac", "MacBook"],
"Phones": ["iPhone 6S", "iPhone 6S Plus"]
]
Then you can at least 2 solutions
1. conditional unwrapping
if let cars = devices["Car"] {
// you have an array of String containing cars here
} else {
print("Ops... no car found")
}
2. guard let
func foo() {
guard let cars = devices["Car"] else {
print("Ops... no car found")
return
}
// you have an array of String containing cars here...
cars.forEach { print($0) }
}
It appears that your printed notificationObject.object is constructed from a JSON string that looks like this:
"{ \"age\": null, \"names\":[\"David\"] }"
The reason that you are hitting your else clause is because age is actually a nil, and not a valid String array. I tried using [String: [String]?] and [String: NSArray?] neither of which seem to work. The type is actually an NSNull (which inherits from NSObject).
So you can cast to [String: AnyObject] and check for NSArray like this:
if let categories = j as? [String: AnyObject] where (categories["age"] is NSArray) {
print("age was array")
} else {
print("age is probably null")
}
You might be better off if your notification object simply omitted the "age" property when the value is null. Then you would be able to cast to [String: [String]].