Exemplo n.º 1
0
 /// <inheritdoc />
 public bool Equals(SortedReadOnlyArray <TValue, TComparer> other)
 {
     return(m_array == other.m_array);
 }
Exemplo n.º 2
0
 public static SortedReadOnlyArray <TValue, TComparer> Instance(TComparer comparer) =>
 SortedReadOnlyArray <TValue, TComparer> .CloneAndSort(
     EmptyArray <TValue>().ToReadOnlyArray(),
     comparer);
Exemplo n.º 3
0
        private int ExceptWithVisitor(SortedReadOnlyArray <TValue, TComparer>[] others, Action <int, TValue>?visit = null)
        {
            // Number of non-excepted items seen so far (returned at the end)
            int size = 0;

            // Indicates if any of 'others' have valid cursors still (this instance may have items greater than all others).
            bool othersRemaining = true;

            // Cursor for the current item to compare with in each of the others.
            var otherCursors = new int[others.Length];

            // We always visit every item in this array since each is potentially (independently) not in the others.
            for (int i = 0; i < Length;)
            {
                bool   found       = false;
                TValue thisCurrent = this[i];

                // If there are others to look at, it is possible that we will find this item.
                if (othersRemaining)
                {
                    // We now try to find the item in at least one of the others (note we don't need to advance the cursors of the rest).
                    othersRemaining = false;
                    for (int otherIdx = 0; !found && otherIdx < others.Length; otherIdx++)
                    {
                        SortedReadOnlyArray <TValue, TComparer> other = others[otherIdx];
                        if (other.Length == otherCursors[otherIdx])
                        {
                            continue;
                        }

                        othersRemaining = true;

                        if (Comparer.Compare(other[otherCursors[otherIdx]], thisCurrent) == 0)
                        {
                            // Exact match (fast path for heavily overlapping sets).
                            otherCursors[otherIdx]++;
                            found = true;
                        }
                        else
                        {
                            // This cursor may be arbitrarily behind (note that we quit looking at additional others for an item when it is first found).
                            // Here we catch up efficiently via binary search. We either find an exact match (non-negative index) or an upper-bound
                            // (encoded negative).
                            int skipToEncoded = other.BinarySearch(thisCurrent, otherCursors[otherIdx], other.Length - otherCursors[otherIdx]);
                            if (skipToEncoded >= 0)
                            {
                                // Exact match. The binary search may have landed in the middle of a sequence of duplicates,
                                // but that's fine; the next cursor advance will take care of that (invariant is advancing cursor points
                                // it at an item at least as high, but not neccesarily higher).
                                otherCursors[otherIdx] = skipToEncoded + 1;
                                found = true;
                            }
                            else
                            {
                                otherCursors[otherIdx] = ~skipToEncoded;
                            }
                        }

                        Contract.Assume(otherCursors[otherIdx] == other.Length || Comparer.Compare(other[otherCursors[otherIdx]], thisCurrent) >= 0);
                    }
                }

                if (!found)
                {
                    visit?.Invoke(size, thisCurrent);

                    size++;
                }

                i++;

                // Skip duplicates in the input sequence (this value was either excepted or not already; cursors have advanced possibly past it).
                while (i < Length && Comparer.Compare(thisCurrent, this[i]) == 0)
                {
                    i++;
                }
            }

            return(size);
        }