I'm looking for a way to use NSCountedSet
in a more Swift
-like way (whatever that means).
Consider the following snippet that I basically translated directly from Objective C
. I iterate over each symbol (a String
) in the set, get its corresponding count, and look up a value for that symbol in a dictionary. Then I multiply that value with the count and add it to the total.
var total = 0
for symbol in symbolSet {
let count = symbolSet.count(for: symbol)
let item = symbolDictionary[symbol as! String]
let value = item?.value
total+= (count * value!)
}
It works, but I am a bit concerned about the unwrapping that Xcode
suggested for me. So I am trying to do this a more Swift
like way so that it is more safe without all the unwrapping.
I started with something like this:
symbolSet.enumerated().map { item, count in
print(item)
print(count)
}
But count here is not the actual count, but an enumeration index.
How do I move forward with this?
You could chain a flatMap
followed by a reduce
operation on your symbolSet
,
flatMap
operation applies attempted conversion of the symbolSet
members to String
reduce
operation computes the weighted sum of the count
of the symbols in the symbolSet
(for the symbols that was successfully converted to String
instances)Example setup:
struct Item {
let value: Int
init(_ value: Int) { self.value = value }
}
let symbolDictionary = [
"+" : Item(1),
"-" : Item(2),
"/" : Item(4),
"*" : Item(8)
]
var symbolSet = NSCountedSet()
symbolSet.add("*") // accumulated: 8
symbolSet.add("/") // accumulated: 8 + 4 = 12
symbolSet.add("+") // accumulated: 12 + 1 = 13
symbolSet.add("-") // accumulated: 13 + 2 = 15
symbolSet.add("+") // accumulated: 15 + 1 = 16
Compute weighted accumulated sum with the chained flatMap
and reduce
operations (expected result: 16
):
let total = symbolSet
.flatMap { $0 as? String } /* <- attempted conversion of each symbol to 'String' */
.reduce(0) { $0 + symbolSet.count(for: $1) * (symbolDictionary[$1]?.value ?? 0) }
/* | ^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | If a key exists for the given symbol as a
| | String, extract the 'value' property of the
| | 'Item' value for this key, otherwise '0'.
| |
| Multiply '...value' or '0' with the 'count' for the given symbol.
\
Add the product to the accumulated sum of the reduce operation. */
print(total) // 16, ok