# Path: py_stringsimjoin/utils/generic_helper.py
# def build_dict_from_table(table, key_attr_index, join_attr_index,
#                           remove_null=True):
#     table_dict = {}
#     for row in table.itertuples(index=False):
#         if remove_null and pd.isnull(row[join_attr_index]):
#             continue
#         table_dict[row[key_attr_index]] = tuple(row)
#     return table_dict
# 
# def get_num_processes_to_launch(n_jobs):        
#     # determine number of processes to launch parallely
#     num_procs = n_jobs
#     if n_jobs < 0:
#         num_cpus = multiprocessing.cpu_count()
#         num_procs = num_cpus + 1 + n_jobs
#     return max(num_procs, 1)
# 
# def split_table(table, num_splits):
#     splits = []
#     split_size = 1.0/num_splits*len(table)
#     for i in xrange(num_splits):
#         splits.append(table[int(round(i*split_size)):
#                             int(round((i+1)*split_size))])
#     return splits
# 
# Path: py_stringsimjoin/utils/validation.py
# def validate_attr(attr, table_cols, attr_label, table_label):
#     """Check if the attribute exists in the table."""
#     if attr not in table_cols:
#         raise AssertionError(attr_label + ' \'' + attr + '\' not found in ' + \
#                              table_label) 
#     return True
# 
# def validate_attr_type(attr, attr_type, attr_label, table_label):
#     """Check if the attribute is not of numeric type."""
#     if attr_type != np.object:
#         raise AssertionError(attr_label + ' \'' + attr + '\' in ' + 
#                              table_label + ' is not of string type.')
#     return True
# 
# def validate_key_attr(key_attr, table, table_label):
#     """Check if the attribute is a valid key attribute."""
#     unique_flag = len(table[key_attr].unique()) == len(table)
#     nan_flag = sum(table[key_attr].isnull()) == 0 
#     if not (unique_flag and nan_flag):
#         raise AssertionError('\'' + key_attr + '\' is not a key attribute ' + \
#                              'in ' + table_label)
#     return True
# 
# def validate_input_table(table, table_label):
#     """Check if the input table is a dataframe."""
#     if not isinstance(table, pd.DataFrame):
#         raise TypeError(table_label + ' is not a dataframe')
#     return True


from joblib import delayed, Parallel
from py_stringsimjoin.utils.generic_helper import build_dict_from_table, \
    get_num_processes_to_launch, split_table
from py_stringsimjoin.utils.validation import validate_attr, \
    validate_attr_type, validate_key_attr, validate_input_table
import pandas as pd
import pyprind
                                      self,
                                      (show_progress and (job_index==n_jobs-1)))
                                          for job_index in range(n_jobs))
            output_table = pd.concat(results)

        return output_table        


def _filter_candset_split(candset,
                          candset_l_key_attr, candset_r_key_attr,
                          ltable, rtable,
                          l_key_attr, r_key_attr,
                          l_filter_attr, r_filter_attr,
                          filter_object, show_progress):
    # Find column indices of key attr and filter attr in ltable
    l_columns = list(ltable.columns.values)
    l_key_attr_index = l_columns.index(l_key_attr)
    l_filter_attr_index = l_columns.index(l_filter_attr)

    # Find column indices of key attr and filter attr in rtable
    r_columns = list(rtable.columns.values)
    r_key_attr_index = r_columns.index(r_key_attr)
    r_filter_attr_index = r_columns.index(r_filter_attr)
    
    # Build a dictionary on ltable
    ltable_dict = build_dict_from_table(ltable, l_key_attr_index,
                                        l_filter_attr_index,
                                        remove_null=False)

    # Build a dictionary on rtable

# Path: py_stringsimjoin/utils/generic_helper.py
# def build_dict_from_table(table, key_attr_index, join_attr_index,
#                           remove_null=True):
#     table_dict = {}
#     for row in table.itertuples(index=False):
#         if remove_null and pd.isnull(row[join_attr_index]):
#             continue
#         table_dict[row[key_attr_index]] = tuple(row)
#     return table_dict
# 
# def get_num_processes_to_launch(n_jobs):        
#     # determine number of processes to launch parallely
#     num_procs = n_jobs
#     if n_jobs < 0:
#         num_cpus = multiprocessing.cpu_count()
#         num_procs = num_cpus + 1 + n_jobs
#     return max(num_procs, 1)
# 
# def split_table(table, num_splits):
#     splits = []
#     split_size = 1.0/num_splits*len(table)
#     for i in xrange(num_splits):
#         splits.append(table[int(round(i*split_size)):
#                             int(round((i+1)*split_size))])
#     return splits
# 
# Path: py_stringsimjoin/utils/validation.py
# def validate_attr(attr, table_cols, attr_label, table_label):
#     """Check if the attribute exists in the table."""
#     if attr not in table_cols:
#         raise AssertionError(attr_label + ' \'' + attr + '\' not found in ' + \
#                              table_label) 
#     return True
# 
# def validate_attr_type(attr, attr_type, attr_label, table_label):
#     """Check if the attribute is not of numeric type."""
#     if attr_type != np.object:
#         raise AssertionError(attr_label + ' \'' + attr + '\' in ' + 
#                              table_label + ' is not of string type.')
#     return True
# 
# def validate_key_attr(key_attr, table, table_label):
#     """Check if the attribute is a valid key attribute."""
#     unique_flag = len(table[key_attr].unique()) == len(table)
#     nan_flag = sum(table[key_attr].isnull()) == 0 
#     if not (unique_flag and nan_flag):
#         raise AssertionError('\'' + key_attr + '\' is not a key attribute ' + \
#                              'in ' + table_label)
#     return True
# 
# def validate_input_table(table, table_label):
#     """Check if the input table is a dataframe."""
#     if not isinstance(table, pd.DataFrame):
#         raise TypeError(table_label + ' is not a dataframe')
#     return True


# Path: py_stringsimjoin/filter/filter.py
from joblib import delayed, Parallel
from py_stringsimjoin.utils.generic_helper import build_dict_from_table, \
    get_num_processes_to_launch, split_table
from py_stringsimjoin.utils.validation import validate_attr, \
    validate_attr_type, validate_key_attr, validate_input_table
import pandas as pd
import pyprind

                                      self,
                                      (show_progress and (job_index==n_jobs-1)))
                                          for job_index in range(n_jobs))
            output_table = pd.concat(results)

        return output_table        


def _filter_candset_split(candset,
                          candset_l_key_attr, candset_r_key_attr,
                          ltable, rtable,
                          l_key_attr, r_key_attr,
                          l_filter_attr, r_filter_attr,
                          filter_object, show_progress):
    # Find column indices of key attr and filter attr in ltable
    l_columns = list(ltable.columns.values)
    l_key_attr_index = l_columns.index(l_key_attr)
    l_filter_attr_index = l_columns.index(l_filter_attr)

    # Find column indices of key attr and filter attr in rtable
    r_columns = list(rtable.columns.values)
    r_key_attr_index = r_columns.index(r_key_attr)
    r_filter_attr_index = r_columns.index(r_filter_attr)
    
    # Build a dictionary on ltable
    ltable_dict = build_dict_from_table(ltable, l_key_attr_index,
                                        l_filter_attr_index,
                                        remove_null=False)

    # Build a dictionary on rtable

    rtable_dict = build_dict_from_table(rtable, r_key_attr_index,