def attributes_to_classes(chip_dataset, chip_key_maker):
    """Extract a set of attributes from a set of Chips and uses them to make
    unique classses.

    The chip_key_maker is a function (or other callable) with the following
    signature:

        chip_key_maker(chip) -> string

    It returns a string derived from the chip. All chips that output the same
    string will be considered as part of the same class for training. An
    example key_maker might do the following:

        chip_key_maker(chip) -> "honda_civic"

    The strings will be sorted first before an index is assigned, so that the
    first string alphabetically will have index 0. This increases the
    reproducibility of the dictionary as only changes to the number of classes,
    not to the chips, will change the dictionary.

    Args:
        chip_dataset: A ChipDataset, or other iterable of Chips
        chip_key_maker: A function that takes a chip and returns a string
            derived from the chip.

    Returns:
        dict: a dictionary mapping the output of chip_key_maker(chip) to a
            class number.
    """
    # First we get all the keys
    keys = set()
    for chip in chip_dataset:
        # Get the class from the specified attributes
        key = chip_key_maker(chip)
        keys.add(key)

    class_to_index = {}
    for index, key in enumerate(sorted(keys)):
        class_to_index[key] = index

    return class_to_index