Reputation: 33
I am new to swift and I am trying to count
the different characters
in a string
but my code returns the value for the whole String
for example:
var string aString = "aabb"
aString.characters.count() //returns 5
counter = 0
let a = "a"
for a in aString.characters {
counter++
} //equally returns 5
Can somebody explain why this is happening and how I could count the different chars?
Upvotes: 0
Views: 17406
Reputation: 359
func repeatedCharaterPrint(inputArray: [String]) -> [String:Int] {
var dict = [String:Int]()
if inputArray.count > 0 {
for char in inputArray {
if let keyExists = dict[char], keyExists != nil {
dict[char] = Int(dict[char] ?? 0) + 1
}else {
dict[char] = 1
}
}
}
return dict
}
let aa = ["a","s","f","s","l","s"]
print(repeatedCharaterPrint(inputArray: aa))
//Answer : "["s": 3, "l": 1, "a": 1, "f": 1]"
Upvotes: 0
Reputation: 49
Construct a dictionary out of a sequence of (key, value) pairs. If we can guarantee that the keys are unique, we can use Dictionary(uniqueKeysWithValues:).
func characterFrequencies(of string: String) -> Dictionary<String.Element, Int> {
let frequencyPair = string.map { ($0, 1) }
return Dictionary(frequencyPair, uniquingKeysWith: +)
}
Usage : print(characterFrequencies(of: "Happy")) Result : ["a": 1, "H": 1, "y": 1, "p": 2]
Upvotes: 0
Reputation: 2433
Updated @Luca Angeletti's answer for Swift5.3 because characters
property is unavailable in newer swift version.
var word = "aabb"
let numberOfChars = word.count // 4
let numberOfDistinctChars = Set(word).count // 2
let occurrenciesOfA = word.filter { $0 == "A" }.count // 0
let occurrenciesOfa = word.filter { $0 == "a" }.count // 2
let occurrenciesOfACaseInsensitive = word.filter { $0 == "A" || $0 == "a" }.count // 2
print(numberOfChars)
print(numberOfDistinctChars)
print(occurrenciesOfA)
print(occurrenciesOfa)
print(occurrenciesOfACaseInsensitive)
Upvotes: 0
Reputation: 1586
The characters
property is deprecated, you can use components(separatedBy:)
to find how many characters in a String. eg,
extension String {
public func numberOfOccurrences(_ string: String) -> Int {
return components(separatedBy: string).count - 1
}
}
let aString = "aabbaa"
let aCount = aString.numberOfOccurrences("a") // aCount = 4
Upvotes: 1
Reputation: 249
This solution is written using hash function , so computation time would be O(1). good for long strings.
//Extension On String and Characters to get Ascii values and Char from Ascii
extension Character {
//Get Ascii Value of Char
var asciiValue:UInt32? {
return String(self).unicodeScalars.filter{$0.isASCII}.first?.value
}
}
extension String {
//Char Char from Ascii Value
init(unicodeScalar: UnicodeScalar) {
self.init(Character(unicodeScalar))
}
init?(unicodeCodepoint: Int) {
if let unicodeScalar = UnicodeScalar(unicodeCodepoint) {
self.init(unicodeScalar: unicodeScalar)
} else {
return nil
}
}
static func +(lhs: String, rhs: Int) -> String {
return lhs + String(unicodeCodepoint: rhs)!
}
static func +=(lhs: inout String, rhs: Int) {
lhs = lhs + rhs
}
}
extension String {
///Get Char at Index from String
var length: Int {
return self.characters.count
}
subscript (i: Int) -> String {
return self[Range(i ..< i + 1)]
}
func substring(from: Int) -> String {
return self[Range(min(from, length) ..< length)]
}
func substring(to: Int) -> String {
return self[Range(0 ..< max(0, to))]
}
subscript (r: Range<Int>) -> String {
let range = Range(uncheckedBounds: (lower: max(0, min(length, r.lowerBound)),
upper: min(length, max(0, r.upperBound))))
let start = index(startIndex, offsetBy: range.lowerBound)
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return self[Range(start ..< end)]
}
}
//Program :
let strk = "aacncjkvkevkklvkdsjkbvjsdbvjkbsdjkvbjdsbvjkbsvbkjwlnkneilhfleknkeiohlgblehgilkbskdbvjdsbvjkdsbvbbvsbdvjlbsdvjbvjkdbvbsjdbjsbvjbdjbjbjkbjkvbjkbdvjbdjkvbjdbvjdbvjbvjdsbjkvbdsjvbkjsbvadvbjkenevknkenvnekvjksbdjvbjkbjbvbkjvbjdsbvjkbdskjvbdsbvjkdsbkvbsdkjbvkjsbvjsbdjkvbdsbvjkbdsvjbdefghaj"
print(strk)
//Declare array of fixes size 26 (characters) or you can say it as a hash table
var freq = [Int](repeatElement(0, count: 26))
func hashFunc(char : Character) -> UInt32 {
guard let ascii = char.asciiValue else {
return 0
}
return ascii - 97 //97 used for ascii value of a
}
func countFre(string:String) {
for i in 0 ... string.characters.count-1 {
let charAtIndex = string[i].characters.first!
let index = hashFunc(char: charAtIndex)
let currentVal = freq[Int(index)]
freq[Int(index)] = currentVal + 1
//print("CurrentVal of \(charAtIndex) with index \(index) is \(currentVal)")
}
for charIndex in 0 ..< 26 {
print(String(unicodeCodepoint: charIndex+97)!,freq[charIndex])
}
}
countFre(string: strk)
Upvotes: -1
Reputation: 59506
It looks there is some confusion about what you really need.
I tried to answer to the 5 most likely interpretations.
var word = "aabb"
let numberOfChars = word.characters.count // 4
let numberOfDistinctChars = Set(word.characters).count // 2
let occurrenciesOfA = word.characters.filter { $0 == "A" }.count // 0
let occurrenciesOfa = word.characters.filter { $0 == "a" }.count // 2
let occurrenciesOfACaseInsensitive = word.characters.filter { $0 == "A" || $0 == "a" }.count // 2
print(occurrenciesOfA)
print(occurrenciesOfa)
print(occurrenciesOfACaseInsensitive)
Upvotes: 19
Reputation: 17544
check this
var aString = "aabb"
aString.characters.count // 4
var counter = 0
let a = "a" // you newer use this in your code
for thisIsSingleCharacterInStringCharactersView in aString.characters {
counter++
}
print(counter) // 4
it simply increase your counter for each character
to calculate number of different characters in you string, you probably can use something 'more advanced', like in next example
let str = "aabbcsdfaewdsrsfdeewraewd"
let dict = str.characters.reduce([:]) { (d, c) -> Dictionary<Character,Int> in
var d = d
let i = d[c] ?? 0
d[c] = i+1
return d
}
print(dict) // ["b": 2, "a": 4, "w": 3, "r": 2, "c": 1, "s": 3, "f": 2, "e": 4, "d": 4]
Upvotes: 13
Reputation: 57124
You code is quite faulty: it should probably start with
let aString = "aabb"
The solutions is to get the characters, put them into a set (unique) and then counting the members of the set:
let differentChars = Set(aString.characters).count
Correctly returns
2
Upvotes: 3