function bucketToMap(array, sorter) {
  const /** !Map<K, !Array<V>> */ buckets = new Map();

  for (let i = 0; i < array.length; i++) {
    const value = array[i];
    const key = sorter(value, i, array);
    if (key !== undefined) {
      // Push the value to the right bucket, creating it if necessary.
      let bucket = buckets.get(key);
      if (!bucket) {
        bucket = [];
        buckets.set(key, bucket);
      }
      bucket.push(value);
    }
  }

  return buckets;
}
Splits an array into disjoint buckets according to a splitting function.
@param {!IArrayLike<V>} array The array.
@param {function(V, number, !IArrayLike<V>):(K|undefined)} sorter Function to
    call for every element.  This takes 3 arguments (the element, the index,
    and the array) and must return a value to use as a key, or undefined, if
    that object should not be placed in a bucket.
@return {!Map<K, !Array<V>>} A map, with keys being all of the unique
    return values of sorter, and values being arrays containing the items for
    which the splitter returned that key.
@template K,V