Replace value `old` with `new` everywhere it appears in-place.

    Implemented by the tabarray method 
    :func:`tabular.tab.tabarray.replace`.

    **Parameters**

            **X** :  numpy ndarray with structured dtype

                    Numpy array for which in-place replacement of `old` with 
                    `new` is to be done.

            **old** : string

            **new** : string

            **strict** :  boolean, optional

            *   If `strict` = `True`, replace only exact occurences of `old`.

            *   If `strict` = `False`, assume `old` and `new` are strings and   
                replace all occurences of substrings (e.g. like 
                :func:`str.replace`)

            **cols** :  list of strings, optional

                    Names of columns to make replacements in; if `None`, make 
                    replacements everywhere.

            **rows** : list of booleans or integers, optional

                    Rows to make replacements in; if `None`, make replacements 
                    everywhere.

    Note:  This function does in-place replacements.  Thus there are issues 
    handling data types here when replacement dtype is larger than original 
    dtype.  This can be resolved later by making a new array when necessary ...

def replace(X, old, new, strict=True, cols=None, rows=None):
    """
    Replace value `old` with `new` everywhere it appears in-place.

    Implemented by the tabarray method 
    :func:`tabular.tab.tabarray.replace`.

    **Parameters**

            **X** :  numpy ndarray with structured dtype

                    Numpy array for which in-place replacement of `old` with 
                    `new` is to be done.

            **old** : string

            **new** : string

            **strict** :  boolean, optional

            *   If `strict` = `True`, replace only exact occurences of `old`.

            *   If `strict` = `False`, assume `old` and `new` are strings and   
                replace all occurences of substrings (e.g. like 
                :func:`str.replace`)

            **cols** :  list of strings, optional

                    Names of columns to make replacements in; if `None`, make 
                    replacements everywhere.

            **rows** : list of booleans or integers, optional

                    Rows to make replacements in; if `None`, make replacements 
                    everywhere.

    Note:  This function does in-place replacements.  Thus there are issues 
    handling data types here when replacement dtype is larger than original 
    dtype.  This can be resolved later by making a new array when necessary ...

    """

    if cols == None:
        cols = X.dtype.names
    elif isinstance(cols, str):
        cols = cols.split(',')

    if rows == None:
        rows = np.ones((len(X),), bool)

    if strict:
        new = np.array(new)
        for a in cols:
            if X.dtype[a] < new.dtype:
                print('WARNING: dtype of column', a, 
                      'is inferior to dtype of ', new, 
                      'which may cause problems.')
            try:
                X[a][(X[a] == old)[rows]] = new
            except:
                print('Replacement not made on column', a, '.')
    else:
        for a in cols:
            QuickRep = True
            try:
                colstr = ''.join(X[a][rows])
            except TypeError:
                print('Not replacing in column', a, 'due to type mismatch.')
            else:
                avoid = [ord(o) for o in utils.uniqify(old + new + colstr)]
                ok = set(range(256)).difference(avoid)
                if len(ok) > 0:
                    sep = chr(list(ok)[0])
                else:
                    ok = set(range(65536)).difference(avoid)
                    if len(ok) > 0:
                        sep = unichr(list(ok)[0])
                    else:
                        print('All unicode characters represented in column', 
                              a, ', can\t replace quickly.')
                        QuickRep = False

                if QuickRep:
                    newrows = np.array(sep.join(X[a][rows])
                                       .replace(old, new).split(sep))
                else:
                    newrows = np.array([aa.replace(old,new) for aa in 
                                        X[a][rows]])
                X[a][rows] = np.cast[X.dtype[a]](newrows)

                if newrows.dtype > X.dtype[a]:
                    print('WARNING: dtype of column', a, 'is inferior to the ' 
                          'dtype of its replacement which may cause problems '
                          '(ends of strings might get chopped off).')