コード例 #1
0
        public void DistinctItems()
        {
            var bag1 = new Bag <string>(new[] { "foo", null, "Foo", "Eric", "FOO", "eric", "bar" },
                                        StringComparer.InvariantCultureIgnoreCase);

            InterfaceTests.TestEnumerableElementsAnyOrder(bag1.DistinctItems(), new string[] { null, "bar", "Eric", "foo" });

            // Make sure enumeration stops on change.
            int count = 0;

            try {
                foreach (string s in bag1.DistinctItems())
                {
                    if (count == 2)
                    {
                        bag1.Add("zippy");
                    }
                    ++count;
                }
                Assert.Fail("should throw");
            }
            catch (Exception e) {
                Assert.IsTrue(e is InvalidOperationException);
                Assert.AreEqual(3, count);
            }
        }
コード例 #2
0
        /// <summary>
        /// Computes the difference of this bag with another bag. The difference of these two bags
        /// is all items that appear in this bag, but not in <paramref name="otherBag"/>. If an item appears X times in this bag,
        /// and Y times in the other bag, the difference contains the item X - Y times (zero times if Y >= X). This bag receives
        /// the difference of the two bags; the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The difference of two bags is computed in time O(M), where M is the size of the
        /// other bag.</para>
        /// </remarks>
        /// <param name="otherBag">Bag to difference with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void DifferenceWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (this == otherBag)
            {
                Clear();
                return;
            }

            // Enumerate each of the items in the other bag. Remove items that need to be
            // removed from this bag.
            foreach (T item in otherBag.DistinctItems())
            {
                var copiesInThis  = NumberOfCopies(item);
                var copiesInOther = otherBag.NumberOfCopies(item);
                var copies        = copiesInThis - copiesInOther;

                if (copies < 0)
                {
                    copies = 0;
                }

                ChangeNumberOfCopies(item, copies);
            }
        }
コード例 #3
0
        /// <summary>
        /// Determines if this bag is a superset of another bag. Neither bag is modified.
        /// This bag is a superset of <paramref name="otherBag"/> if every element in
        /// <paramref name="otherBag"/> is also in this bag, at least the same number of
        /// times.
        /// </summary>
        /// <remarks>IsSupersetOf is computed in time O(M), where M is the number of unique items in
        /// <paramref name="otherBag"/>.</remarks>
        /// <param name="otherBag">Bag to compare to.</param>
        /// <returns>True if this is a superset of <paramref name="otherBag"/>.</returns>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public bool IsSupersetOf(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (otherBag.Count > Count)
            {
                return(false); // Can't be a superset of a bigger set
            }
            // Check each item in the other set to make sure it is in this set.
            return(otherBag.DistinctItems().All(item => NumberOfCopies(item) >= otherBag.NumberOfCopies(item)));
        }
コード例 #4
0
        /// <summary>
        /// Determines if this bag is equal to another bag. This bag is equal to
        /// <paramref name="otherBag"/> if they contain the same number of
        /// of copies of equal elements.
        /// </summary>
        /// <remarks>IsSupersetOf is computed in time O(N), where N is the number of unique items in
        /// this bag.</remarks>
        /// <param name="otherBag">Bag to compare to</param>
        /// <returns>True if this bag is equal to <paramref name="otherBag"/>, false otherwise.</returns>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public bool IsEqualTo(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            // Must be the same size.
            if (otherBag.Count != Count)
            {
                return(false);
            }

            // Check each item to make sure it is in this set the same number of times.
            return(otherBag.DistinctItems().All(item => NumberOfCopies(item) == otherBag.NumberOfCopies(item)));
        }
コード例 #5
0
        /// <summary>
        /// Computes the sum of this bag with another bag. The sum of two bags
        /// is all items from both of the bags. If an item appears X times in one bag,
        /// and Y times in the other bag, the sum contains the item (X+Y) times. This bag receives
        /// the sum of the two bags, the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The sum of two bags is computed in time O(M), where M is the size of the
        /// other bag..</para>
        /// </remarks>
        /// <param name="otherBag">Bag to sum with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void SumWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (this == otherBag)
            {
                // Not very efficient, but an uncommon case.
                AddMany(otherBag);
                return;
            }

            // Enumerate each of the items in the other bag. Add items that need to be
            // added to this bag.
            foreach (var item in otherBag.DistinctItems())
            {
                var copiesInThis  = NumberOfCopies(item);
                var copiesInOther = otherBag.NumberOfCopies(item);

                ChangeNumberOfCopies(item, copiesInThis + copiesInOther);
            }
        }
コード例 #6
0
        /// <summary>
        /// Computes the union of this bag with another bag. The union of two bags
        /// is all items from both of the bags. If an item appears X times in one bag,
        /// and Y times in the other bag, the union contains the item Maximum(X,Y) times. This bag receives
        /// the union of the two bags, the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The union of two bags is computed in time O(M+N), where M and N are the size of the
        /// two bags.</para>
        /// </remarks>
        /// <param name="otherBag">Bag to union with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void UnionWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (otherBag == this)
            {
                return; // Nothing to do
            }
            // Enumerate each of the items in the other bag. Add items that need to be
            // added to this bag.
            foreach (var item in otherBag.DistinctItems())
            {
                int copiesInThis  = NumberOfCopies(item);
                int copiesInOther = otherBag.NumberOfCopies(item);

                if (copiesInOther > copiesInThis)
                {
                    ChangeNumberOfCopies(item, copiesInOther);
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Computes the symmetric difference of this bag with another bag. The symmetric difference of two bags
        /// is all items that appear in either of the bags, but not both. If an item appears X times in one bag,
        /// and Y times in the other bag, the symmetric difference contains the item AbsoluteValue(X - Y) times. This bag receives
        /// the symmetric difference of the two bags; the other bag is unchanged.
        /// </summary>
        /// <remarks>
        /// <para>The symmetric difference of two bags is computed in time O(M + N), where M is the size of the
        /// larger bag, and N is the size of the smaller bag.</para>
        /// </remarks>
        /// <param name="otherBag">Bag to symmetric difference with.</param>
        /// <exception cref="InvalidOperationException">This bag and <paramref name="otherBag"/> don't use the same method for comparing items.</exception>
        public void SymmetricDifferenceWith(Bag <T> otherBag)
        {
            CheckConsistentComparison(otherBag);

            if (this == otherBag)
            {
                Clear();
                return;
            }

            // Enumerate each of the items in the other bag. Add items that need to be
            // added to this bag.
            foreach (var item in otherBag.DistinctItems())
            {
                var copiesInThis  = NumberOfCopies(item);
                var copiesInOther = otherBag.NumberOfCopies(item);
                var copies        = Math.Abs(copiesInThis - copiesInOther);

                if (copies != copiesInThis)
                {
                    ChangeNumberOfCopies(item, copies);
                }
            }
        }