Find object by comparing two array - swift

I have two array, which has the same model.
I'm trying to find the object where it has the same id. I have tried this method which I can find it but how I can make it without for loop?
for item in userList {
let userSelection = user.list.first(where: {$0.id == item.id})
item.approved = userSelection.approved
print(userSelection)
}

Try something like this
let userSelection = user.list.filter({userList.map({$0.id}).contains({$0.id})})
Explanation:
//get all the ids from one list
let ids = userList.map({$0.id})
//filter the second list by including all the users whose id is in the first list
let userSelection = user.list.filter({ids.contains({$0.id})})

If you don't care about performance, you can use set.intersection:
let set1:Set<UserType> = Set(userList)
let set2:Set<UserType> = Set(user.list)
let commonItems = set1.intersection(set2)// Intersection of two sets

Even if your model is not Hashable, you can use sets to perform the validation:
if Set(userList.map{$0.id}).subtracting(user.list.map{$0.id}).count == 0
{
// all entries in userList exist in user.list
}
else
{
// at least one entry of userList is not in user.list
}

Related

check if there much id inside dictionary than holds objects

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)

Swift Realm Results to Editable object or array

OK, I understand that I can not modify the results of a Realm Object.
So what is best way to change the data.
First I get all the Realm data as Results< Month >
let m = Month.getAllEntriesByDateAsc()
Now I need to loop through all the data to modify it. (This is a function to recalculate the entire table data.)
So I want to loop through the data and do something like:
for i in m {
var d = i
// perform calculations like
d.value = 9999
}
I want to do all the modifying on d.
Is these some sort of mapping I can use to create the new edible object from the Realm data?
Previously I did something like this:
for i in m {
let d = Month()
d.value = i.value
d.status = i.status
}
But there are now to many variables.
I guest what I need to so change the Realm Object to the Model object?
And the .toArray() stuff will not work inside the loop? Not sure why.
Thanks.
extension Results {
func toArray<T>(ofType: T.Type) -> [T] {
var array = [T]()
for i in 0 ..< count {
if let result = self[i] as? T {
array.append(result)
}
}
return array
}
}
From here

"Unwrapping" data retrieved from Firebase

So I have managed to retrieve some data from Firebase and it looks like this when printed:
[Resturant.CustomerList(key: "-LQQlhEmNZb8Kaha9uCk", customerLastName:
“Kendrick”, customerFirstName: “Anna”, customerSeat: "100",
customerOrder: “Noodle”, Timestamp: 1541290545703.0)]
Question: How do I unwrap them so I can put individual value into other String variables?
I tried many ways but I get errors such cannot subscript a value of type [CustomerList] with an index of type String if I do something like let custName = self.list["Name"] as? String
ps. CustomerList is a struct
pps. The print out of list is what is shown
As you have a list of CustomerList objects i.e, [CustomerList] so you should first get a single object from this list. Lets say we want the very first object from this list to access its properties then we can do it as below,
if let firstCustomer = self.list.first {
let firstName = firstCustomer.customerFirstName
let lastName = firstCustomer.customerLastName
}
If you want to access an object at a specific index then you can do as below,
let index = 0
let customer = self.list[index]
let firstName = customer.customerFirstName
let lastName = customer.customerLastName
To find a particular customer, you can filter that as below,
let johny = self.list.filter{ $0.customerFirstName == "Jonhny"}.first {
print(johny.customerLastName)
}
To get a custom list created from the customers list, you can use map as below,
let lastNamesArray = self.list.map({ $0.customerLastName })

Appending to dictionary of [character: [object]] returns 0 key/value pair

I'm trying to show a tableview similar to contacts with my list of users.
I declare a global variable of friends that will store the first character of a name and a list of users whose first name start with that
var friends = [Character: [User]]()
In my fetch method, I do this
for friend in newFriends {
let letter = friend.firstName?[(friend.firstName?.startIndex)!]
print(letter)
self.friends[letter!]?.append(friend)
}
After this, I should have my friends array with the first letter of the name and the users that fall in it; however, my friends dictionary is empty.
How do I fix this?
Edit: I'm following this tutorial and he doesnt exactly the same.. Swift: How to make alphabetically section headers in table view with a mutable data source
Rather than using Character as the key, use String. You need to be sure to init the [User] array for every new First Initial key you insert into groupedNames. I keep an array of groupedLetters to make it easier to get a section count
var groupedNames = [String: [User]]()
var groupedLetters = Array<String>()
func filterNames() {
groupedNames.removeAll()
groupedLetters.removeAll()
for friend in newFriends {
let index = friend.firstName.index(friend.firstName.startIndex, offsetBy: 0)
let firstLetter = String(friend.firstName[index]).uppercased()
if groupedNames[firstLetter] != nil {
//array already exists, just append
groupedNames[firstLetter]?.append(friend)
} else {
//no array for that letter key - init array and store the letter in the groupedLetters array
groupedNames[firstLetter] = [friend]
groupedLetters.append(firstLetter)
}
}
}
Creating a Dictionary structure with Characters as keys & values as Array of User will be more succinct.
The error occurs because you are declaring an empty dictionary, that means you have to add a key / empty array pair if there is no entry for that character.
Consider also to consolidate the question / exclamation marks
class User {
let firstName : String
init(firstName : String) {
self.firstName = firstName
}
}
var friends = [Character: [User]]()
let newFriends = [User(firstName:"foo"), User(firstName:"bar"), User(firstName:"baz")]
for friend in newFriends {
let letter = friend.firstName[friend.firstName.startIndex]
if friends[letter] == nil {
friends[letter] = [User]()
}
friends[letter]!.append(friend)
}

Swift: Core data trouble with to-many relationship and mutableOrderedSetValueForKey

I'm having trouble understanding why my ordered set is only saving 1 entry.
my code is as follows:
let newInovice = NSEntityDescription.insertNewObjectForEntityForName("Invoice", inManagedObjectContext: managedObjectContext) as! InvoiceMO
let itemDetail = NSEntityDescription.insertNewObjectForEntityForName("InvoiceDetail", inManagedObjectContext: managedObjectContext) as! InvoiceDetailMO
// Data Entry
// Add invoice number to Invoice
newInovice.invoiceNumber = getInvoiceNum()
newInovice.date = invoiceDate
// Create mutable set to add details
for items in details {
itemDetail.detail = items[PropKeys.itemDescription]
let item = items[PropKeys.itemPrice] ?? "0"
let itemDouble = { return Double(item) ?? 0 }()
itemDetail.price = itemDouble
let quantity = items[PropKeys.itemQuantity] ?? "1"
let quantityInt = { return Int(quantity) ?? 0 }()
itemDetail.quantity = quantityInt
print("This is the item detail before insertion: \(itemDetail)")
newInovice.mutableOrderedSetValueForKey("invoiceDetails").addObject(itemDetail)
subtotal += itemDouble * Double(quantityInt)
}
print("details.Count = \(details.count)")
print("Start Mutable \(newInovice.invoiceDetails?.count) End Mutable Set")
// Save the Data
do {
try newCustomer.managedObjectContext?.save()
} catch {
print(error)
}
I've read through the docs and it seems like I'm doing this correctly but it only adds one entry to the ordered set even though I've iterated through the array of objects.
Here is my debugger showing the entries before they are added and the count of the managed object after adding the objects.
debuggerWindow
my relationships are set up as follows:
relationships
You are only creating one InvoiceDetail outside your for loop. Obviously, you will have to create one for each detail that is contained in the data array.