Finding the difference between two Arrays

Published on: October 6, 2019

Many applications work with data, often they are built to retrieve data and display this data to the user in a table view, collection view, list (if you're using SwiftUI) or a different kind of component. It's not uncommon for this data to change and when it does you might be interested in figuring out what elements were added to the data and which items were removed. This isn't always straightforward so up until now you might have written code something like the following:

func didFetchNewRecipes(_ newRecipes: [Recipe]) {
  recipes = newRecipes
  tableView.reloadData()
}

Simple and effective, much easier than figuring out the difference and only reloading the cells that have changed. On iOS 13, you can use new methods on any collection that conforms to BiDirectionalCollection to determine the changes between two collections as long as the items that are contained in the collection conform to Equatable. You can then use the information from this method to update a table view:

func didFetchNewRecipes(_ newRecipes: [Recipe]) {
  let changes = newRecipes.difference(from: recipes)

  let insertedIndexPaths = changes.insertions.compactMap { change -> IndexPath? in
    guard case let .insert(offset, _, _) = change
      else { return nil }

    return IndexPath(row: offset, section: 0)
  }

  let removedIndexPaths = changes.removals.compactMap { change -> IndexPath? in
    guard case let .remove(offset, _, _) = change
      else { return nil }

    return IndexPath(row: offset, section: 0)
  }

  self.recipes = newRecipes
  tableView.beginUpdates()
  tableView.insertRows(at: insertedIndexPaths, with: .automatic)
  tableView.deleteRows(at: removedIndexPaths, with: .automatic)
  tableView.endUpdates()
}

Tip:
If your elements are not Equatable, use the differences(from:by:) method to supply a closure where you can perform your own comparison to determine if two elements are equal.

Cool stuff right? What kind of applications do you see for this kind of method? Let me know on Twitter!

Subscribe to my newsletter