0

Found a cute way of counting the occurrences of character in a String:

let inputString = "test this string"
var frequencies : [Character: Int] = [:]

let baseCounts = zip(
    inputString, repeatElement(1,count: Int.max))
frequencies = Dictionary(baseCounts, uniquingKeysWith: +)

with the result

["i": 2, "r": 1, "n": 1, "e": 1, "s": 3, " ": 2, "g": 1, "t": 4, "h": 1]

However I tried to use a range for the elements such that

let secondBaseCounts = zip(inputString, 0...)
frequencies = Dictionary(secondBaseCounts, uniquingKeysWith: +)

but get the incorrect result:

["i": 20, "r": 12, "n": 14, "e": 1, "s": 20, " ": 13, "g": 15, "t": 19, "h": 6]

Why?

stevenpcurtis
  • 1,907
  • 3
  • 21
  • 47

2 Answers2

3

Your second attempt doesn't implement what you meant to implement. zip(inputString, 0...) simply maps the Int index of each character to the character itself.

So the value of secondBaseCounts will be

["t", 0), ("e", 1), ("s", 2), ("t", 3), (" ", 4), ("t", 5), ("h", 6), ("i", 7), ("s", 8), (" ", 9), ("s", 10), ("t", 11), ("r", 12), ("i", 13), ("n", 14), ("g", 15)]

Calling Dictionary(secondBaseCounts, uniquingKeysWith: +) sums each value associated with repeating keys, meaning that the values in your final frequencies dictionary will be the sum of all indices where a certain character occurs in inputString rather than the count of occurrences of that character.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
1

I am answering this question without using any Build-In methods. Most likely to be asked in Interviews.

var inputString = "test this string"

extension String {
    
    func countCharacterOccurances() -> Dictionary<String, Any> {
        var occuranceDict : [String : Int] = [:]
       
        for i in self {
            var count = 1
            if occuranceDict[String(i)] == nil  {
                occuranceDict[String(i)] = count
            }
            else {
                count = occuranceDict[String(i)] ?? 0
                count += 1
                occuranceDict[String(i)] = count
            }
        }
        return occuranceDict as Dictionary<String, Any>
    }
}
var characterOccuranceDict = inputString.countCharacterOccurances()

Output : ["h": 1, "t": 4, "i": 2, "g": 1, "s": 3, "r": 1, " ": 2, "n": 1, "e": 1]

The following code is useful if you want a dictionary that is sorted alphabetically by Keys. Otherwise, you can print characterOccuranceDict.

Problem statement:- "write a program to count consecutive characters in the string and combine them in a string in given order"

let sortedDictionary = characterOccuranceDict.sorted { $0.key < $1.key }
sortedDictionary.forEach { (item) in 
    finalStr = finalStr + item.key + String(describing: item.value)
}
print(finalStr)

inputString = "AAABBCCCCD"

Output : A3B2C4D1

Shrikant Phadke
  • 358
  • 2
  • 11