Skip to content →

Tag: filter

Evolution of a Dictionary Filter

Let’s say we have some arbitrary dictionary:

let fullset = ["Apple": 123, "Boxcar": 234, "Candle": 345, "Downtown": 456, "Eclipse": 567, "Ferrous": 678, "Gallapagos": 789, "Helicopter": 890, "Indiana": 901, "Jarrod": 012]

and we want to write a function to determine whether that dictionary contains a subset of elements, which for purposes of illustration is given as:

let subset = ["Candle": 345, "Ferrous": 678, "Indiana": 901]

A straighforward solution might look like so:

func dictionary(dict: [String: Int], contains subset: [String: Int]) -> Bool {
  var matches = 0
  for (key, value) in subset {
    if dict[key] == value {
      matches += 1
    }
  }
  return matches == subset.count
}

print(dictionary(fullset, contains: subset)) // prints "true"

A solution that takes advantage of the Swift where clause and thereby allows us to remove the inner for-loop modifies this to:

func dictionary(dict: [String: Int], contains subset: [String: Int]) -> Bool {
  var matches = 0
  for (key, value) in subset where dict[key] == value {
    matches += 1
  }
  return matches == subset.count
}

That’s cool. But remembering that the SequenceType function filter(_:) iterates over a collection and returns those elements that meet a certain condition, we can evolve this function further to:

func dictionary(dict: [String: Int], contains subset: [String: Int]) -> Bool {
  let matches = dict.filter() { $0.1 == subset[$0.0] }
  return matches.count == subset.count
}

where $0 refers to the tuple (String, Int) corresponding to the dictionary key-value types, with $0.0 and $0.1 referring to the first and second values within that tuple, respectively.

Finally, we can clean things up a bit and reduce this to one line without loss of—but, arguably, added—clarity:

func dictionary(dict: [String: Int], contains subset: [String: Int]) -> Bool {
  return dict.filter { key, value in value == subset[key] }.count == subset.count
}
Leave a Comment