Construct a composite distance appropriate for matching address data. NOTE:
    this utility function does not guarantee that the output composite distance
    will work with a particular dataset and model. When the composite distance
    is applied in a particular context, the feature types and individual
    distance functions must be appropriate for the given model.

    Parameters
    ----------
    number, street, city, state, zip_code : string, optional
        Name of the SFrame column for the feature corresponding to the address
        component. Each feature name is mapped to an appropriate distance
        function and scalar multiplier.

    Returns
    -------
    dist : list
        A composite distance function, mapping sets of feature names to distance
        functions.

    Examples
    --------
    >>> homes = turicreate.SFrame({'sqft': [1230, 875, 1745],
    ...                          'street': ['phinney', 'fairview', 'cottage'],
    ...                          'city': ['seattle', 'olympia', 'boston'],
    ...                          'state': ['WA', 'WA', 'MA']})
    ...
    >>> my_dist = turicreate.distances.build_address_distance(street='street',
    ...                                                     city='city',
    ...                                                     state='state')
    >>> my_dist
    [[['street'], 'jaccard', 5],
     [['state'], 'jaccard', 5],
     [['city'], 'levenshtein', 1]]

def build_address_distance(number=None, street=None, city=None, state=None,
                           zip_code=None):
    """
    Construct a composite distance appropriate for matching address data. NOTE:
    this utility function does not guarantee that the output composite distance
    will work with a particular dataset and model. When the composite distance
    is applied in a particular context, the feature types and individual
    distance functions must be appropriate for the given model.

    Parameters
    ----------
    number, street, city, state, zip_code : string, optional
        Name of the SFrame column for the feature corresponding to the address
        component. Each feature name is mapped to an appropriate distance
        function and scalar multiplier.

    Returns
    -------
    dist : list
        A composite distance function, mapping sets of feature names to distance
        functions.

    Examples
    --------
    >>> homes = turicreate.SFrame({'sqft': [1230, 875, 1745],
    ...                          'street': ['phinney', 'fairview', 'cottage'],
    ...                          'city': ['seattle', 'olympia', 'boston'],
    ...                          'state': ['WA', 'WA', 'MA']})
    ...
    >>> my_dist = turicreate.distances.build_address_distance(street='street',
    ...                                                     city='city',
    ...                                                     state='state')
    >>> my_dist
    [[['street'], 'jaccard', 5],
     [['state'], 'jaccard', 5],
     [['city'], 'levenshtein', 1]]
    """

    ## Validate inputs
    for param in [number, street, city, state, zip_code]:
        if param is not None and not isinstance(param, str):
            raise TypeError("All inputs must be strings. Each parameter is " +
                            "intended to be the name of an SFrame column.")

    ## Figure out features for levenshtein distance.
    string_features = []

    if city:
        string_features.append(city)

    if zip_code:
        string_features.append(zip_code)


    ## Compile the distance components.
    dist = []

    if number:
        dist.append([[number], 'jaccard', 1])

    if street:
        dist.append([[street], 'jaccard', 5])

    if state:
        dist.append([[state], 'jaccard', 5])

    if len(string_features) > 0:
        dist.append([string_features, 'levenshtein', 1])

    return dist