示例#1
0
        public static ndarray in1d(ndarray ar1, ndarray ar2, bool assume_unique = false, bool invert = false)
        {
            /*
             * Test whether each element of a 1-D array is also present in a second array.
             *
             * Returns a boolean array the same length as `ar1` that is True
             * where an element of `ar1` is in `ar2` and False otherwise.
             *
             * We recommend using :func:`isin` instead of `in1d` for new code.
             *
             * Parameters
             * ----------
             * ar1 : (M,) array_like
             *  Input array.
             * ar2 : array_like
             *  The values against which to test each value of `ar1`.
             * assume_unique : bool, optional
             *  If True, the input arrays are both assumed to be unique, which
             *  can speed up the calculation.  Default is False.
             * invert : bool, optional
             *  If True, the values in the returned array are inverted (that is,
             *  False where an element of `ar1` is in `ar2` and True otherwise).
             *  Default is False. ``np.in1d(a, b, invert=True)`` is equivalent
             *  to (but is faster than) ``np.invert(in1d(a, b))``.
             *
             *  .. versionadded:: 1.8.0
             *
             * Returns
             * -------
             * in1d : (M,) ndarray, bool
             *  The values `ar1[in1d]` are in `ar2`.
             *
             * See Also
             * --------
             * isin                  : Version of this function that preserves the
             *                      shape of ar1.
             * numpy.lib.arraysetops : Module with a number of other functions for
             *                      performing set operations on arrays.
             *
             * Notes
             * -----
             * `in1d` can be considered as an element-wise function version of the
             * python keyword `in`, for 1-D sequences. ``in1d(a, b)`` is roughly
             * equivalent to ``np.array([item in b for item in a])``.
             * However, this idea fails if `ar2` is a set, or similar (non-sequence)
             * container:  As ``ar2`` is converted to an array, in those cases
             * ``asarray(ar2)`` is an object array rather than the expected array of
             * contained values.
             *
             * .. versionadded:: 1.4.0
             *
             * Examples
             * --------
             * >>> test = np.array([0, 1, 2, 5, 0])
             * >>> states = [0, 2]
             * >>> mask = np.in1d(test, states)
             * >>> mask
             * array([ True, False,  True, False,  True])
             * >>> test[mask]
             * array([0, 2, 0])
             * >>> mask = np.in1d(test, states, invert=True)
             * >>> mask
             * array([False,  True, False,  True, False])
             * >>> test[mask]
             * array([1, 5])
             */

            // Ravel both arrays, behavior for the first array could be different
            ar1 = np.asarray(ar1).ravel();
            ar2 = np.asarray(ar2).ravel();


            // This code is run when
            // a) the first condition is true, making the code significantly faster
            // b) the second condition is true (i.e. `ar1` or `ar2` may contain
            // arbitrary objects), since then sorting is not guaranteed to work

            if (len(ar2) < 10 * Math.Pow(len(ar1), 0.145))
            {
                ndarray mask;
                if (invert)
                {
                    mask = np.ones(new shape(len(ar1)), dtype: np.Bool);
                    foreach (dynamic a in ar2)
                    {
                        if (ar1.TypeNum == NPY_TYPES.NPY_STRING)
                        {
                            string  aa   = a.ToString();
                            ndarray temp = ar1.NotEquals(aa);
                            mask &= temp;
                        }
                        else
                        {
                            ndarray temp = ar1 != a;
                            mask &= temp;
                        }
                    }
                }
                else
                {
                    mask = np.zeros(new shape(len(ar1)), dtype: np.Bool);
                    foreach (dynamic a in ar2)
                    {
                        if (ar1.TypeNum == NPY_TYPES.NPY_STRING)
                        {
                            string  aa   = a.ToString();
                            ndarray temp = ar1.Equals(aa);
                            mask |= temp;
                        }
                        else
                        {
                            ndarray temp = ar1 == a;
                            mask |= temp;
                        }
                    }
                }
                return(mask);
            }

            // Otherwise use sorting

            ndarray rev_idx = null;

            if (!assume_unique)
            {
                var temp = np.unique(ar1, return_inverse: true, return_index: true);
                ar1     = temp.data;
                rev_idx = temp.indices;

                ar2 = np.unique(ar2).data;
            }

            ndarray ar = np.concatenate(ar1, ar2);

            // We need this to be a stable sort, so always use 'mergesort'
            // here. The values from the first array should always come before
            // the values from the second array.
            ndarray order = ar.ArgSort(kind: NPY_SORTKIND.NPY_MERGESORT);
            ndarray bool_ar;

            ndarray sar = ar.A(order);

            if (invert)
            {
                bool_ar = (sar.A("1:")).NotEquals(sar.A(":-1"));
            }
            else
            {
                bool_ar = (sar.A("1:")).Equals(sar.A(":-1"));
            }
            ndarray flag = np.concatenate(new ndarray[] { bool_ar, np.array(new bool[] { invert }) });
            ndarray ret  = np.empty(ar.shape, dtype: np.Bool);

            ret[order] = flag;

            if (assume_unique)
            {
                return(ret.A(":" + len(ar1).ToString()));
            }
            else
            {
                return(ret.A(rev_idx));
            }
        }