Long form of this Swift syntax - swift

The following will compare the first element's id with compr's id, and return true if matched.
I am confused with {} of .first { } != nil syntax. How does the longer form of this pattern condense to to the following:
private(set) var arr : [Arrs] = []
func isPresent(for compr: Compr) -> Bool {
Arrs.first { comp.id == $0.id } != nil
}

First, change the line to the following so it compiles:
arr.first { compr.id == $0.id } != nil
This is just using trailing closure syntax for the first(where:) method. It can also be written as:
arr.first(where: { compr.id == $0.id }) != nil
But a better way would be to do the following:
arr.contains { compr.id == $0.id }

Related

How do you assign and unwrap an optional array object in Swift?

I'm trying to invert a binary tree in Swift using the iterative approach. Essentially I just keep looping through each node, and putting it into a stack array. This array should be an array of optional nodes. Here is my code:
func invertTree(_ root: TreeNode?) -> TreeNode? {
if root != nil {
stack.append(root)
} else {
return root
}
var stack = [TreeNode?]()
while stack.count > 0 {
if stack.last == nil {
stack.removeLast()
} else {
var tempLeft : TreeNode? = stack.last!.left
stack.last!.left = stack.last!.right
stack.last!.right = tempLeft
if stack.last!.left != nil {
stack.append(stack.last!.left)
}
if stack.last.right != nil {
stack.append(stack.last!.right)
}
}
}
return root
}
I'm getting all sorts of optional errors. In particular, when I set:
var tempLeft : TreeNode? = stack.last!.left
I'm not sure why it says "value of optional type TreeNode? must be unwrapped to refer to member 'left' of unwrapped base type 'TreeNode' in solution.swift"
I don't understand why it's telling me to unwrap the optional, when I'm already force unwrapping it. I don't want to unwrap the .left node since I want to include nils in my stack for the iteration to work.
Any help would be greatly appreciated.
stack.last is a doubly optional TreeNode: TreeNode??.
You could use optional chaining like so:
if stack.last == nil {
stack.removeLast()
} else {
stack.last
var tempLeft : TreeNode? = stack.last!?.left
stack.last!?.left = stack.last!?.right
stack.last!?.right = tempLeft
if stack.last!?.left != nil {
stack.append(stack.last!?.left)
}
if stack.last??.right != nil {
stack.append(stack.last!?.right)
}
}
Or avoid the drama and use pattern matching:
if case let node?? = stack.last {
let tempLeft = node.left
node.left = node.right
node.right = tempLeft
...
Other than that, it seems that there are other areas of your code that you need to tend to. For example, using stack before its declaration.
Alternative implementation
Here is a solution that uses a stack:
class Solution {
func invertTree(_ root: TreeNode?) -> TreeNode? {
guard let r = root else {
return nil
}
var stack = [r]
while let node = stack.last {
let temp = node.left
node.left = node.right
node.right = temp
stack.removeLast()
if let left = node.left { stack.append(left) }
if let right = node.right { stack.append(right) }
}
return r
}
}

A set is not equal but an array from this set is equal?

I work with unit-tests and encounter this problem:
I have some classes and each have their own isEqual() method. At some point I came to a situation where an unit-test sometimes fails and sometimes succeeds.
I check the equality of two objects that contain a set of objects. Here the the problem arises. Sometimes the test "obj1.mySet == obj2.mySet" fails - sometimes not. I test this with only one object in each set (mySet). The test for the equality of this objects (in mySet) itself succeeds.
I tried some hours to find a mistake in my code, but couldn't find any. Now I have a workaround that helps to pass the test, but I do not understand, what's going on. I have a method within the test-objects, that returns the objects of the set as an (ordered) array. When I test the equality of this arrays, the test always succeeds.
Do someone know, what’s going on?
Update:
In my BaseClass
func hash(into hasher: inout Hasher) { hasher.combine(firebaseID) }
static func == (lhs: FirebaseObject, rhs: FirebaseObject) -> Bool { return lhs.isEqual(to: rhs) }
func isEqual(to object: Any?) -> Bool {
guard object != nil && object is FirebaseObject else { return false }
let value = object as! FirebaseObject
return firebaseID == value.firebaseID && name == value.name
}
In the SubClass
override func isEqual(to object: Any?) -> Bool {
guard object != nil && object! is MealPlanned else { return false }
let obj = object as! MealPlanned
var result = ""
if !super.isEqual(to:obj) { result.append("fbObject ") }
if portions != obj.portions { result.append("portions ") }
if imgID != obj.imgID { result.append("imgID ") }
if meal != obj.meal { result.append("meal ") }
if date != obj.date { result.append("date ") }
if portionsInBaseMeal != obj.portionsInBaseMeal {result.append("portionsInBaseMeal ") }
if getIngrediencesInMeals() != obj.getIngrediencesInMeals() { result.append("ingrediencesInMeals ") }
if result.count > 0 {
if (showsDifference) { print("difference in MealPlanned <\(obj.name ?? "Fehler")>: \(result)") }
return false
}
return true
}
I did it this way, to find and print the problem.
This version succeeds.
if getIngrediencesInMeals() != obj.getIngrediencesInMeals() { result.append("ingrediencesInMeals ")
getIngrediencesInMeals() returns the set as an ordered array.
In this way the test sometimes succeeds sometimes fails:
if ingrediences != ingrediences { result.append("ingrediencesInMeals ")
This returns the ordered array:
func getIngrediencesInMeals() -> [IngredienceInMeals] { return ingrediences.sorted{ $0.position < $1.position } }
in IngredienceInMeals
override func isEqual(to object: Any?) -> Bool {
guard object != nil && object! is IngredienceInMeals else { return false }
let obj = object as! IngredienceInMeals
var result = ""
if !super.isEqual(to:obj) { result.append("fbObject ")}
if unit != obj.unit { result.append("unit ")}
if quantity != obj.quantity { result.append("quantity ")}
if ingredience != obj.ingredience { result.append("ingredience ")}
if position != obj.position { result.append("position ")}
if result.count > 0 {
if (showsDifference) { print("difference in IngredienceInMeal <\(obj.name ?? "Fehler")>: \(result)") }
return false
}
return true
}
if you want to compare two objects use Equatable protocol method in your object class
example of compare two objects
class ItemModel : Equatable {
var TypeOfOffer : String?
var TypeOfSelling : String?
var Address : String?
var NumberOfRoom : String?
var Price : String?
var Image : String?
var ID : String?
var itemId : String?
init(TypeOfOffer : String? , TypeOfSelling : String?, Address : String?, NumberOfRoom : String? , Price : String?, Image : String?, ID : String?, itemId : String? )
{
self.TypeOfOffer = TypeOfOffer
self.TypeOfSelling = TypeOfSelling
self.Address = Address
self.NumberOfRoom = NumberOfRoom
self.Price = Price
self.Image = Image
self.ID = ID
self.itemId = itemId
}
static func == (lhs: ItemModel, rhs: ItemModel) -> Bool {
var isIt = true
isIt = (lhs.TypeOfOffer == "" || lhs.TypeOfOffer == rhs.TypeOfOffer)
&& (lhs.TypeOfSelling == "" || lhs.TypeOfSelling == rhs.TypeOfSelling)
&& (lhs.Address == "" || lhs.Address == rhs.Address)
&& (lhs.NumberOfRoom == "" || lhs.NumberOfRoom == rhs.NumberOfRoom)
&& (lhs.Price == "" || lhs.Price == rhs.Price)
return isIt
}
}
Compare two instances of an object in Swift!

Unwrapping dictionary values Swift

I'm creating an adjacency list in Swift, storing an array of nodes. However, when adding an edge from an existing node I need to check if the from key exists in any of the children, and if it does check if the to value exists in the same. It seems to be a mess s.t.
func addEdge(from: String, to: String) {
//the full code for addEdge is incomplete here
if (children.contains{ $0.nodes[from] != nil}) {
for child in children {
if (child.nodes[from] != nil) {
if (!(child.nodes[from]?.contains{$0 == to})!){
child.nodes[from]?.append(to)
}
}
}
}
}
Children is
var children = [Node]()
and Node is
class Node: Hashable {
var nodes = [String:[String]]()
var hashValue: Int{ return nodes.hashValue }
static func == (lhs: Node, rhs: Node) -> Bool {
return lhs.nodes.keys == rhs.nodes.keys
}
}
Now it works, but seems really ugly. There must be a better way in Swift, but what is it?
Assuming that you do not wish to change the way you have implemented the above code but want to improve readability, you can utilise if let and optional chaining to make your code cleaner and more readable.
func addEdge(from: String, to: String) {
//the full code for addEdge is incomplete here
if children.contains{ $0.nodes[from] != nil } {
for child in children {
if let fromNode = child.nodes[from], fromNode.contains{$0 == to} {
fromNode.append(to)
}
}
}
}
Swift Optional Chaining
Try something like:
if (children.contains{ $0.nodes[from] != nil}) {
children.filter { $0.nodes[from] != nil }.
compactMap { $0.nodes[from] }.
filter { !($0.nodes[from]!.contains{$0 == to}) }.
forEach { $0.nodes[from]?.append(to) }
}

Enum pattern matching as a parameter to a function call

I've setup a playground with an example:
enum CarType : Equatable {
case wheeled(wheels: Int)
case flying
public static func ==(lhs: CarType, rhs: CarType) -> Bool {
return lhs.enumName == rhs.enumName
}
var enumName: String {
let stuff = "\(self)".split(separator: "(").first!
return String(describing: stuff)
}
}
var typesPresentAtMyParty = [CarType.wheeled(wheels:4), .wheeled(wheels:4), .flying]
let aKnownType = CarType.flying
if case aKnownType = typesPresentAtMyParty[2] {
print("Was the type")
}
func isPresent(type: CarType, inArray: [CarType]) -> Bool {
return inArray.filter {
if case type = $0 {
return true
}
return false
}.first != nil
}
func isWheeled(inArray: [CarType]) -> Bool {
return inArray.filter {
if case .wheeled = $0 {
return true
}
return false
}.first != nil
}
isPresent(type: .flying, inArray: typesPresentAtMyParty)
isPresent(type: .wheeled, inArray: typesPresentAtMyParty)
The last line here does not compile. While i can do if case .wheeled = $0 ignoring associated type as a check, i cannot find a way of doing the same in a function call isPresent(type: CarType, inArray: [CarType]), when sending isPresent(type: .wheeled, inArray: typesPresentAtMyParty)
Is there a way of writing a function that takes only the valid pattern matching part of the enum as a parameter?
It is not possible to pass partially constructed enums to a function. Partially constructed enums are not valid values, and they only work in pattern matching because the compiler has a concrete value to work with - the one from the right side of the pattern.
These being said, you could easily rewrite your functions to better, more swiftier versions.
Firstly, you don't need isPresent, you can simply use contains:
typesPresentAtMyParty.contains { $0 == .flying }
typesPresentAtMyParty.contains { if case . wheeled = $0 { return true } else { return false } }
Similarly, isWheeled can be shortened (and renamed, for better semantics):
func isWheeled(_ carType: CarType) -> Bool {
if case . wheeled = carType { return true } else { return false }
}
which can pe passed to contains:
let hasWeeled = typesPresentAtMyParty.contains(where: isWheeled)

Swift: Early return if both optionals are nil?

Bit of a dilemma about coding style in Swift:
Say we have 2 variables which can both be nil (Optionals), and we have to get the value of one of them or return early if both are nil.
In Objective-C it would be written this way:
- (void)authenticate:(Account*)anAccount {
Account* account = anAccount ?: self.defaultAccount();
if (!account) return;
doLotsOfThings(account);
}
I could figure out a few ways to rewrite it in Swift, but all of them introduced code smell.
Swift: with code duplication
func authenticate(_account: Account?) {
if let account = _account {
self.doLotsOfThings(account)
} else if let account = self.defaultAccount {
self.doLotsOfThings(account)
}
}
Swift: this solves the code duplication but doesn't feel very Swift-y.
func authenticate(_account: Account?) {
if _account == nil && self.defaultAccount == nil { return }
let account = _account == nil ? self.defaultAccount! : _account!
self.doLotsOfThings(account)
}
Question is; is there a way to do this using guard ? If not, are there any better ways to deal with this case?
Thanks.
That's a use-case for the nil-coalescing operator ??:
func authenticate(_account: Account?) {
if let account = _account ?? self.defaultAccount {
self.doLotsOfThings(account)
}
}
or early-return with guard:
func authenticate(_account: Account?) {
guard let account = _account ?? self.defaultAccount else {
return
}
self.doLotsOfThings(account)
}
The expression
_account ?? self.defaultAccount
evaluates to _account if _account != nil, and to
self.defaultAccount otherwise.
Also ?? is a "short-circuiting" operator like && and ||,
which means that in
your case, self.defaultAccount is not even evaluated if
_account != nil.