I have an array of letters, and want to match the characters against the letters and then do something to that letter (in this case turn it yellow) and then remove that matched
So you have an array of Character(s)
:
let letters = Array("randomness")
An array of special Character(s)
let specials = Array("ness")
And you want to remove from letters
, the specials
right?
Here it is:
let set = Set(specials)
let filtered = letters.filter { !set.contains($0) }
filtered // ["r", "a", "d", "o", "m"]
This version keep also consider the occurrences of a char
let letters = Array("randomness")
let specials = Array("ness")
var occurrencies = specials.reduce([Character:Int]()) { (var dict, char) in
dict[char] = (dict[char] ?? 0) + 1
return dict
}
let filtered = letters.filter {
if let num = occurrencies[$0] where num > 0 {
occurrencies[$0] = num - 1
return false
} else {
return true
}
}
filtered // ["r", "a", "d", "o", "m", "n"]
Yes it is very dangerous to modify the number of items in an array while being enumerated.
Imagine you have an array of three items, the range is 0...2
. In the first iteration you delete the first item, then array[2] is now array[1] and there is no item at index 2 any more.
Either you enumerate the array backwards, so the index of the removed item is always equal to or higher than the current index or you use a variable to collect the indexes to be deleted and delete the characters by range.
Of course Swift has more reliable functions to accomplish this task as mentioned by the others therefore it's not needed to use enumerate
In this case.
just fixed it after reading the SDs post here: Swift buttons hidden fatal error: Array index out of range
I updated this question in case it helps anyone else.
I added an if statement to check the index was still in range. Not really sure why this works but it does :-)
var letters = Array(word1) // [r,a,n,d,o,m,n,e,s,s]
var characters = Array(specialLetters) // [n,e,s,s]
// delete the special letters
for (index, element) in enumerate(characters) {
if letter == element {
tile.letterLabel.textColor = UIColor.yellowColor()
// remove that character from the array so can't be matched twice.
// first check that the index is still in range.
if index < characters.count { // added this if statement
characters.removeAtIndex(index)
}
}
}
For this purpose (removing elements of an array), you may want to use an indexing generator. Let me give an example:
var array = [1, 2, 3, 4]
var ig = array.generate()
var index = 0
var element = ig.next()
while element != nil {
if element == 2 {
array.removeAtIndex(index)
} else {
index = index + 1
}
element = ig.next()
}
May i suggest a different approach where instead of removing from the initial array you make a new one, from which you can exclude the characters you don't want to appear in your array in the first place.
PS: keep in mind the following code works with Swift 2.0 Xcode 7 beta 6
var letters : [Character] = ["a","b", "c"]
var lettersToBeRemoved : [Character] = ["a"]
var newLetters : [Character] = []
for i in letters
{
for j in lettersToBeRemoved
{
if i == j
{
continue
}
newLetters.append(i)
}
}
print(newLetters)