Reputation: 12238
Note: answer must be a single string used in a format argument of an NSPredicate object. As in:
var pred1:NSPredicate = NSPredicate.init(format: *ANSWER*)
Suppose I have the following dictionary:
var ticketState:Dictionary =
[
"orderTotal":1.2,
"payments":
[
[
"authCode":"12345",
"isVoid":"false",
"amount":1.0
],
[
"authCode":"54321",
"isVoid":"false",
"amount":0.2
]
],
"associatedWithReturn":false
]
Now I want an NSPredicate
to check if all the amounts sum up to equal the order total.
Something like:
var cond1:String = "sum($payments[].amount == $orderTotal)"
Note: I cannot use array filtering or a second predicate.
I can access the first payment amount like this:
var cond1:String = "$payments[1].amount > 0" //works, returns true
This will return true. I just want to check that the sum of all the amounts in payments equals the order Total. This should be a simple operation defined by a single predicate.
How do I write a one-line NSPredicate declaration that accomplishes this?
Note: there is a very specific reason I need it to be a one-line, single NSPredicate initialization format string. But that's an implementation detail; don't worry about it, because someone else might have a different reason than me for needing the same type of initialization.
Upvotes: 1
Views: 1477
Reputation: 12238
var cond1:String = "[email protected] == $orderTotal"
var pred1:NSPredicate = NSPredicate.init(format: cond1)
var rule1:GKRule = GKRule.init(predicate: pred1, assertingFact:"completeable", grade:1.0)
var ruleSys:GKRuleSystem = GKRuleSystem.init()
ruleSys.addRule(rule1)
ruleSys.state.addEntriesFromDictionary(ticketState)
ruleSys.evaluate()
print(ruleSys.facts)
Returns ["completeable"]
.
Thanks sage444 for the tip that led me to that.
To put it another way:
Swift:
var pred1:NSPredicate =
NSPredicate.init(format: "[email protected] == $orderTotal")
Objective C:
NSPredicate *pred1 =
[[NSPredicate alloc]initWithFormat:@"[email protected] == $orderTotal"];
My purpose for this is to initialize an Apple GameplayKit GKRule
object, which takes an NSPredicate
object as an argument. However I think it could have many other applications.
Upvotes: 1
Reputation: 12594
Use following code to get sum
var totalAmount:Float = (ticketState.valueForKeyPath("[email protected]") as! NSNumber).floatValue;
Now you can compare it or do anything you want.
For other related operators like average,count etc. you can check other collection operators at following link:
Upvotes: 1
Reputation: 285160
This is a native Swift solution which uses to built-in functions
map
to put the amount
values into an arrayreduce
to add the valueslet payments = ticketState["payments"] as! [[String:AnyObject]]
let amountSum = payments.map{$0["amount"] as! Double}.reduce(0, combine: {$0 + $1})
Upvotes: 1