def find_keys(key_list, keys, require_match=False):
    """Find the indices of keys into a list of keys.

    Parameters
    ----------
    key_list : iterable
    keys : iterable
    require_match : bool
        Require that `key_list` contain every element of `keys`,
        and if not, raise ValueError.

    Returns
    -------
    indices : list of int or None
        List of the same length as `keys` containing
        the indices of `keys` in `key_list`.  If `require_match`
        is False, then this can also contain None for keys
        that are not contained in `key_list`.
    """
    # Significantly faster than repeated calls to find_key
    try:
        dct = {tuple(kk): ii for ii, kk in enumerate(key_list)}
        index = [dct.get(tuple(key)) for key in keys]
    except TypeError:
        dct = {kk: ii for ii, kk in enumerate(key_list)}
        index = [dct.get(key) for key in keys]

    if require_match and any([ind is None for ind in index]):
        raise ValueError("Could not find all of the keys.")
    else:
        return index