Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Except and intersect variations #257

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Reorganized Except and Intersect files
Split each method group into its own file, and nested them under
SetFilter.cs which contains the common implementation and is nested
under MoreEnumerable.cs.
JamesFaix committed May 1, 2016
commit e6f4bf485fa09d5582da422fb3cbd1b282a523f3
145 changes: 2 additions & 143 deletions MoreLinq/ExceptAll.cs
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@
namespace MoreLinq {
using System;
using System.Collections.Generic;
using System.Linq;

static partial class MoreEnumerable {

@@ -48,148 +47,8 @@ public static IEnumerable<TSource> ExceptAll<TSource>(this IEnumerable<TSource>
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");

return ExceptAllKeysImpl(first, second, x => x, comparer);
}

/// <summary>
/// Returns the sequence of elements in the first sequence which aren't
/// in the second sequence, according to a given key selector.
/// </summary>
/// <remarks>
/// This is not a set operation like <see cref="MoreLinq.MoreEnumerable.ExceptBy{TSource, TKey}(
/// System.Collections.Generic.IEnumerable{TSource}, System.Collections.Generic.IEnumerable{TSource}, System.Func{TSource, TKey})"/>;
/// if multiple elements in <paramref name="first"/> have equal keys, all such elements are returned.
/// This operator uses deferred execution and streams results from <paramref name="first"/>,
/// but the entire set of keys from <paramref name="second"/> is cached as soon as execution begins.
/// Duplicate keys from <paramref name="second"/> are not relevant and are discarded when <paramref name="second"/> is cached.
/// </remarks>
/// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/> and used for comparing values.</typeparam>
/// <param name="first">The sequence of potentially included elements.</param>
/// <param name="second">The sequence of elements whose keys may prevent elements in <paramref name="first"/> from being returned.</param>
/// <param name="keySelector">The mapping from source element to key.</param>
/// <returns>The sequence of elements from <paramref name="first"/> whose key was not also a key for
/// any element in <paramref name="second"/>, including values with duplicate keys from <paramref name="first"/>.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="first"/>, <paramref name="second"/>, or
/// <paramref name="keySelector"/> is <c>null</c>.</exception>
public static IEnumerable<TSource> ExceptAllBy<TSource, TKey>(this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TKey> keySelector) {
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (keySelector == null) throw new ArgumentNullException("keySelector");

return ExceptAllKeysImpl(first, second.Select(keySelector), keySelector, null);
}

/// <summary>
/// Returns the sequence of elements in the first sequence which aren't
/// in the second sequence, according to a given key selector and equality comparer.
/// </summary>
/// <remarks>
/// This is not a set operation like <see cref="MoreLinq.MoreEnumerable.ExceptBy{TSource, TKey}(
/// System.Collections.Generic.IEnumerable{TSource}, System.Collections.Generic.IEnumerable{TSource}, System.Func{TSource, TKey})"/>;
/// This operator uses deferred execution and streams results from <paramref name="first"/>,
/// but the entire set of keys from <paramref name="second"/> is cached as soon as execution begins.
/// Duplicate keys from <paramref name="second"/> are not relevant and are discarded when <paramref name="second"/> is cached.
/// </remarks>
/// <typeparam name="TSource">The type of the elements in the input sequences.</typeparam>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/> and used for comparing values.</typeparam>
/// <param name="first">The sequence of potentially included elements.</param>
/// <param name="second">The sequence of elements whose keys may prevent elements in <paramref name="first"/> from being returned.</param>
/// <param name="keySelector">The mapping from source element to key.</param>
/// <param name="keyComparer">The equality comparer to use to determine whether or not keys are equal.
/// If null, the default equality comparer for <c>TSource</c> is used.</param>
/// <returns>The sequence of elements from <paramref name="first"/> whose key was not also a key for
/// any element in <paramref name="second"/>, including values with duplicate keys from <paramref name="first"/>.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="first"/>, <paramref name="second"/>, or
/// <paramref name="keySelector"/> is <c>null</c>.
/// If <paramref name="keyComparer"/> is <c>null</c>, the default equality comparer for <typeparamref name="TSource"/> is used.</exception>
public static IEnumerable<TSource> ExceptAllBy<TSource, TKey>(this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> keyComparer) {
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (keySelector == null) throw new ArgumentNullException("keySelector");

return ExceptAllKeysImpl(first, second.Select(keySelector), keySelector, keyComparer);
}

/// <summary>
/// Returns the sequence of elements in the first sequence,
/// whose keys are not in the second sequence, according to a given key selector.
/// </summary>
/// <remarks>
/// This is not a set operation like <see cref="MoreLinq.MoreEnumerable.ExceptKeys{TSource, TKey}(
/// System.Collections.Generic.IEnumerable{TSource}, System.Collections.Generic.IEnumerable{TKey}, System.Func{TSource, TKey})"/>;
/// if multiple elements in <paramref name="first"/> have equal keys, all such elements are returned.
/// This operator uses deferred execution and streams results from <paramref name="first"/>,
/// but the entire set of keys from <paramref name="second"/> is cached as soon as execution begins.
/// Duplicate keys from <paramref name="second"/> are not relevant and are discarded when <paramref name="second"/> is cached.
/// </remarks>
/// <typeparam name="TSource">The type of source and result elements.</typeparam>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/> and used for comparing values.</typeparam>
/// <param name="first">The sequence of potentially included elements.</param>
/// <param name="second">The set of keys which may prevent elements in <paramref name="first"/> from being returned.</param>
/// <param name="keySelector">The mapping from source element to key.</param>
/// <returns>The sequence of elements from <paramref name="first"/> whose key is not in <paramref name="second"/>,
/// including values with duplicate keys from <paramref name="first"/>.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="first"/>, <paramref name="second"/>, or
/// <paramref name="keySelector"/> is <c>null</c>.</exception>
public static IEnumerable<TSource> ExceptAllKeys<TSource, TKey>(this IEnumerable<TSource> first,
IEnumerable<TKey> second,
Func<TSource, TKey> keySelector) {

if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (keySelector == null) throw new ArgumentNullException("keySelector");

return ExceptAllKeysImpl(first, second, keySelector, null);
}

/// <summary>
/// Returns the sequence of elements from the first collection,
/// whose keys are not in the second collection, according to a given key selector and equality comparer.
/// </summary>
/// <remarks>
/// This is not a set operation like <see cref="MoreLinq.MoreEnumerable.ExceptKeys{TSource, TKey}(
/// System.Collections.Generic.IEnumerable{TSource}, System.Collections.Generic.IEnumerable{TKey}, System.Func{TSource, TKey})"/>;
/// if multiple elements in <paramref name="first"/> have equal keys, all such elements are returned.
/// This operator uses deferred execution and streams results from <paramref name="first"/>,
/// but the entire set of keys from <paramref name="second"/> is cached as soon as execution begins.
/// Duplicate keys from <paramref name="second"/> are not relevant and are discarded when <paramref name="second"/> is cached.
/// </remarks>
/// <typeparam name="TSource">The type of source and result elements.</typeparam>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/> and used for comparing values.</typeparam>
/// <param name="first">The sequence of potentially included elements.</param>
/// <param name="second">The set of keys which may prevent elements in <paramref name="first"/> from being returned.</param>
/// <param name="keySelector">The mapping from source element to key.</param>
/// <param name="keyComparer">The key comparer. If <c>null</c>, uses the default TKey equality comparer.</param>
/// <returns>The sequence of elements from <paramref name="first"/> whose key is not in <paramref name="second"/>,
/// including values with duplicate keys from <paramref name="first"/>.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="first"/>, <paramref name="second"/>, or
/// <paramref name="keySelector"/> is <c>null</c>.
/// If <paramref name="keyComparer"/> is <c>null</c>, the default equality comparer for <typeparamref name="TSource"/> is used.</exception>
public static IEnumerable<TSource> ExceptAllKeys<TSource, TKey>(this IEnumerable<TSource> first,
IEnumerable<TKey> second,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> keyComparer) {

if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (keySelector == null) throw new ArgumentNullException("keySelector");

return ExceptAllKeysImpl(first, second, keySelector, keyComparer);
}

private static IEnumerable<TSource> ExceptAllKeysImpl<TSource, TKey>(IEnumerable<TSource> first,
IEnumerable<TKey> second,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> keyComparer) {

var keys = new HashSet<TKey>(second, keyComparer);
return first.Where(x => !keys.Contains(keySelector(x)));
return SetFilterImpl(first, second, x => x, comparer, (hs, k) => !hs.Contains(k));
}

}
}
90 changes: 90 additions & 0 deletions MoreLinq/ExceptAllBy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#region License and Terms
// MoreLINQ - Extensions to LINQ to Objects
// Copyright (c) 2008 Jonathan Skeet. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

namespace MoreLinq {
using System;
using System.Collections.Generic;
using System.Linq;

static partial class MoreEnumerable {

/// <summary>
/// Returns the sequence of elements in the first sequence which aren't
/// in the second sequence, according to a given key selector.
/// </summary>
/// <remarks>
/// This is not a set operation like <see cref="MoreLinq.MoreEnumerable.ExceptBy{TSource, TKey}(
/// System.Collections.Generic.IEnumerable{TSource}, System.Collections.Generic.IEnumerable{TSource}, System.Func{TSource, TKey})"/>;
/// if multiple elements in <paramref name="first"/> have equal keys, all such elements are returned.
/// This operator uses deferred execution and streams results from <paramref name="first"/>,
/// but the entire set of keys from <paramref name="second"/> is cached as soon as execution begins.
/// Duplicate keys from <paramref name="second"/> are not relevant and are discarded when <paramref name="second"/> is cached.
/// </remarks>
/// <typeparam name="TSource">The type of the elements of the input sequences.</typeparam>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/> and used for comparing values.</typeparam>
/// <param name="first">The sequence of potentially included elements.</param>
/// <param name="second">The sequence of elements whose keys may prevent elements in <paramref name="first"/> from being returned.</param>
/// <param name="keySelector">The mapping from source element to key.</param>
/// <returns>The sequence of elements from <paramref name="first"/> whose key was not also a key for
/// any element in <paramref name="second"/>, including values with duplicate keys from <paramref name="first"/>.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="first"/>, <paramref name="second"/>, or
/// <paramref name="keySelector"/> is <c>null</c>.</exception>
public static IEnumerable<TSource> ExceptAllBy<TSource, TKey>(this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TKey> keySelector) {
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (keySelector == null) throw new ArgumentNullException("keySelector");

return SetFilterImpl(first, second.Select(keySelector), keySelector, null, (hs, k) => !hs.Contains(k));
}

/// <summary>
/// Returns the sequence of elements in the first sequence which aren't
/// in the second sequence, according to a given key selector and equality comparer.
/// </summary>
/// <remarks>
/// This is not a set operation like <see cref="MoreLinq.MoreEnumerable.ExceptBy{TSource, TKey}(
/// System.Collections.Generic.IEnumerable{TSource}, System.Collections.Generic.IEnumerable{TSource}, System.Func{TSource, TKey})"/>;
/// This operator uses deferred execution and streams results from <paramref name="first"/>,
/// but the entire set of keys from <paramref name="second"/> is cached as soon as execution begins.
/// Duplicate keys from <paramref name="second"/> are not relevant and are discarded when <paramref name="second"/> is cached.
/// </remarks>
/// <typeparam name="TSource">The type of the elements in the input sequences.</typeparam>
/// <typeparam name="TKey">The type of the key returned by <paramref name="keySelector"/> and used for comparing values.</typeparam>
/// <param name="first">The sequence of potentially included elements.</param>
/// <param name="second">The sequence of elements whose keys may prevent elements in <paramref name="first"/> from being returned.</param>
/// <param name="keySelector">The mapping from source element to key.</param>
/// <param name="keyComparer">The equality comparer to use to determine whether or not keys are equal.
/// If null, the default equality comparer for <c>TSource</c> is used.</param>
/// <returns>The sequence of elements from <paramref name="first"/> whose key was not also a key for
/// any element in <paramref name="second"/>, including values with duplicate keys from <paramref name="first"/>.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="first"/>, <paramref name="second"/>, or
/// <paramref name="keySelector"/> is <c>null</c>.
/// If <paramref name="keyComparer"/> is <c>null</c>, the default equality comparer for <typeparamref name="TSource"/> is used.</exception>
public static IEnumerable<TSource> ExceptAllBy<TSource, TKey>(this IEnumerable<TSource> first,
IEnumerable<TSource> second,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> keyComparer) {
if (first == null) throw new ArgumentNullException("first");
if (second == null) throw new ArgumentNullException("second");
if (keySelector == null) throw new ArgumentNullException("keySelector");

return SetFilterImpl(first, second.Select(keySelector), keySelector, keyComparer, (hs, k) => !hs.Contains(k));
}
}
}
Loading