Search code examples
arraysswiftdictionarykey

Count occurrences of values in dictionaries in Swift


Can somebody help me to solve this problem? Thank you in advance

import Foundation

func countOccurance(topics: [String : [String]], reviews: [String]) -> [String : Int] {
    
    var count: [String: Int] = [:]
    
    for (topicKeys, topicValues) in topics {
        for key in topicKeys {
            for val in topicValues {
                if reviews.contains(val) {
                   // count += 1
                    count["\(key)"]! += 1
                }
            }
        }
    }
    return count
}

let topics = [
    "price" : ["cheap", "expensive", "price"],
    "business" : ["small", "medium", "large"]
]
let reviews = "large company with expensive items. Some are very cheap"
let result = countOccurance(topics: topics, reviews: [reviews])

for (key,value) in result.enumerated() {
    print("\(key) : \(value)")
}

I want to return dictionary in below format. Sample output { "price" : 2 "business" : 1 }


Solution

  • Here is a possible method of doing this, which should be slightly faster than excessive use of loops.

    Method:

    1. Split each review into its individual words.
    2. Create a dictionary with the key being the review word and the value being the frequency.
    3. Loop through every topic, then loop through every keyword in that topic.
    4. If the keyword is in reviewsDict, get the number of occurrences and add it on to count's occurrences.
    5. Return dictionary result containing topics and their frequencies.

    Solution:

    func countOccurance(topics: [String: [String]], reviews: [String]) -> [String : Int] {
        var reviewsDict: [String: Int] = [:]
        for review in reviews {
            let reviewWords = review.components(separatedBy: CharacterSet.letters.inverted)
    
            for word in reviewWords {
                guard !word.isEmpty else { continue }
                reviewsDict[word.lowercased(), default: 0] += 1
            }
        }
    
        var count: [String: Int] = [:]
        for (topic, topicKeywords) in topics {
            for topicKeyword in topicKeywords {
                guard let occurrences = reviewsDict[topicKeyword] else { continue }
                count[topic, default: 0] += occurrences
            }
        }
    
        return count
    }
    

    Result:

    0 : (key: "price", value: 2)
    1 : (key: "business", value: 1)