I'm comparing the characters contained within two words. In seeking to accomplish this, Set
(aka NSSet
) seemed like the way to go to accomplish this task. I've discovered it returns false positives on matches, so I am attempting to use CountedSet
(aka NSCountedSet
) instead.
I'm able to initialize a Set
without issue, but I can't get the CountedSet
initializer to work. Here's what I've done...
I start with a String
:
// Let's say myTextField.text = "test"
let textFieldCharacters = myTextField.text?.characters
// word is a string from the ENABLE list of words
let wordCharacters = word.characters
Then I dump the characters into an Array
:
var wordCharactersArray = [Character]()
for character in wordCharacters {
wordCharacterArray.append(character)
}
var textFieldCharactersArray = [Character]()
for character in textFieldCharacters {
wordCharacterArray.append(character)
}
Then I create a Set
from the character arrays:
let textFieldSet = Set<Character>(textFieldCharactersArray)
let wordSet = Set<Character>(wordCharactersArray)
Finally, I test to see if the textFieldSet
is a superSet of wordSet
with the following:
textFieldSet.isSuperset(of: wordSet)
Going back to my example, if myTextField.text
is "test", I'm returning values for word
whose characters are a superset of the wordSet
, but the counts of the individual elements don't match the character counts of myTextField.text
In researching my issue, I've found CountedSet
(fka NSCountedSet
), which I think would resolve my issue. It has two method signatures:
public convenience init(array: [AnyObject])
public convenience init(set: Set<NSObject>)
I've tried initializing the 2 sets of characters like so:
let textFieldSet = CountedSet(array: textFieldCharacterArray)
let wordSet = CountedSet(array: wordCharacterArray)
I get the following error for the sets
Cannot convert value of type '[Character]' to expected argument type '[AnyObject]'.
So I tried initializing the set like this:
let textFieldSet = CountedSet(array: textFieldCharacterArray as! [AnyObject])
Which yields the following error:
'AnyObject' is not a subtype of 'Character'
I've also tried to initialize the CountedSet
with a Set
, per the method signature, but I get errors when I try to do that, too.
Any suggestions how to initialize a CountedSet
would be greatly appreciated.
You are correct that if you need to compare not just the presents of elements but also their count, you should use CountedSet
, which is a renaming of NSCountedSet
for swift 3.0. The problem you are running into is CountedSet
can only accept elements that are objects and Characters
are not. As Eric D points out in their comment, the easies way to get around this is by mapping your [Character]
to [String]
which will bridge to [NSString]
.
You are not running into this problem using Set
, because it is a native Swift collection type that initialize with elements of any type. This is why you can initialize a Set
with [Character]
.
To see the difference:
let word = "helo"
let wordCharacters = Array(word.characters)
let wordSet = Set(wordCharacters)
let wordCharStrings = wordCharacters.map{String($0)}
let wordCountedSet = CountedSet(array: wordCharStrings)
let textField = "hello"
let textFieldCharacters = Array(textField.characters)
let textSet = Set(textFieldCharacters)
let textFieldCharStrings = textFieldCharacters.map{String($0)}
let textFieldCountedSet = CountedSet(array: textFieldCharStrings)
textFieldCountedSet.isSubset(of: wordCountedSet as! Set<NSObject>) // returns false, but if word had two or more l's it would return true
textSet.isSubset(of: wordSet) // returns true