function zipBaseAndCompareItems(baseItems, compareItems) {
  const groupedByKey = _.groupIntoMap(
    [
      ...baseItems.map((item, i) => ({item, kind: 'base', index: i})),
      ...compareItems.map((item, i) => ({item, kind: 'compare', index: i})),
    ],
    entry => replaceNondeterministicStrings(getItemKey(entry.item))
  );

  /** @type {Array<{base?: DetailItemEntry, compare?: DetailItemEntry}>} */
  const zipped = [];

  for (const entries of groupedByKey.values()) {
    const baseItems = entries.filter(entry => entry.kind === 'base');
    const compareItems = entries.filter(entry => entry.kind === 'compare');

    if (baseItems.length > 1 || compareItems.length > 1) {
      // The key is not actually unique, just treat all as added/removed.
      for (const entry of entries) {
        zipped.push({[entry.kind]: entry});
      }

      continue;
    }

    zipped.push({base: baseItems[0], compare: compareItems[0]});
  }

  return zipped;
}
@param {Array<Record<string, any>>} baseItems
@param {Array<Record<string, any>>} compareItems
@return {Array<{base?: DetailItemEntry, compare?: DetailItemEntry}>}