3

Could you please help me to simplify the flow below? the scope is to count how many time each element is duplicate within the given array.

var test = [1,2,3,4,5,6,7,8,5,9,3,3,9,9,9]

var testCount = [Int:Int]()

for curr in test {
    if let x = testCount[curr] {
        testCount[curr] = x  + 1
        continue;
    }
    testCount[curr] = 1
}

print(testCount)

I'm working on it in order to have something like:

test.map_duplicate() or map_duplicate(test)

3 Answers 3

4
extension Array where Element: Hashable {

    func mergeDuplicates() -> [Element: Int] {
        var result = [Element: Int]()

        self.forEach({ result[$0] = result[$0] ?? 0 + 1 })

        return result
    }

}

var test = [1,2,3,4,5,6,7,8,5,9,3,3,9,9,9]

let testCount = test.mergeDuplicates()

print(testCount)

The code above provides an extension to any Array type that holds Hashable elements (anything else is not eligible to be the key of a dictionary). Method mergeDuplicates produces the dictionary you want. In its implementation, forEach() executes a closure over every element in the array (this is typically more straightforward and transparent alternative to old-fashioned for-loop). Then on each iteration we check whether there is already existing value in the dictionary with a running count (and use nil-coalescing operator ?? to handle cases when a particular value was not yet met before, hence it's zero). Then increment, and store (back) into the dictionary.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! A small bug though. self.forEach{ result[$0] = (result[$0] ?? 0) + 1 }
3

You could extend SequenceType to have a function freq which does exactly what you need here.

extension SequenceType where Self.Generator.Element: Hashable {
    func freq() -> [Self.Generator.Element: Int] {
        return reduce([:]) { (var accu: [Self.Generator.Element: Int], element) in
            accu[element] = accu[element]?.successor() ?? 1
            return accu
        }
    }
}

Comments

0
var countForNumber = 0

for number in test {
    test.forEach({ if number == $0 { countForNumber++ } })
    testCount[number] = countForNumber
    countForNumber = 0
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.