Home > Software design >  Count frequency of an element in a Swift array of elements
Count frequency of an element in a Swift array of elements

Time:04-11

I want to count the frequency of false m's in an array of elements:

    import UIKit

struct aW: Hashable, Codable {
    var day: Int
    var w: Double
    var m: Bool
}

let array = [
    aW(day: 0, w: 32.62, m: true),
    aW(day: 1, w: 32.40, m: true),
    aW(day: 2, w: 32.16, m: true),
    aW(day: 3, w: 32.01, m: false),
    aW(day: 4, w: 31.81, m: true),
    aW(day: 5, w: 31.61, m: false),
    aW(day: 6, w: 31.41, m: false),
    aW(day: 7, w: 31.20, m: true),
    aW(day: 8, w: 31.01, m: true),
    aW(day: 9, w: 30.83, m: true)]

Also I want to select the first element with a false occurence.

I found a lot of examples for frequencies for arrays of strings or int's. But how do you do this with an array of such elements?

CodePudding user response:

You can simply use reduce. If the element's m property is true return the same partial result otherwise return the partial result plus one:

let count = array.reduce(0) { $1.m ? $0 : $0   1 }
count // 3

To get the first element that is false you can use first where predicate:

if let element = array.first(where: { !$0.m }) {
    print(element)  // AW(day: 3, w: 32.01, m: false)
}

Note that it is Swift naming convention to name your structs starting with an uppercase letter. You should also use better descriptive naming.

CodePudding user response:

Map the items in an array of tuples with the property you want to count as key:

let mappedItems = array.map { ($0.m, 1) }

Then use this Dictionary initializer to add the values if it finds duplicate keys.

let counts = Dictionary(mappedItems, uniquingKeysWith:  )

this prints:

[true: 7, false: 3]

CodePudding user response:

Just in case if you’re interested. Below is the playground combine version for @Leo Dabus answer.

var subscriptions = Set<AnyCancellable>()

struct aW: Hashable, Codable {
    var day: Int
    var w: Double
    var m: Bool
}

let array = [
     aW(day: 0, w: 32.62, m: true),
     aW(day: 1, w: 32.40, m: true),
     aW(day: 2, w: 32.16, m: true),
     aW(day: 3, w: 32.01, m: false),
     aW(day: 4, w: 31.81, m: true),
     aW(day: 5, w: 31.61, m: false),
     aW(day: 6, w: 31.41, m: false),
     aW(day: 7, w: 31.20, m: true),
     aW(day: 8, w: 31.01, m: true),
     aW(day: 9, w: 30.83, m: true)].publisher
   
      array
     .reduce(0) {$1.m ? $0 : $0   1}
     .sink(receiveValue: { print($0) }) // 3
     .store(in: &subscriptions)
  • Related