質問
そのリストが別のリストのサブセットであるかどうかを確認する方法についてのアイデアはありますか?
具体的には、私は
List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };
LINQを使用して、t2がt1のサブセットであることを確認するにはどうすればよいですか
解決
bool isSubset = !t2.Except(t1).Any();
他のヒント
セットを使用する場合は、リストの代わりにHashSetを使用します。その後、単に IsSubsetOf()
を使用できます。HashSet<double> t1 = new HashSet<double>{1,3,5};
HashSet<double> t2 = new HashSet<double>{1,5};
bool isSubset = t2.IsSubsetOf(t1);
LINQは使用していません。 :-(
リストを使用する必要がある場合、@ Jaredのソリューションは、存在する繰り返し要素を削除する必要があるという警告に対応します。
単体テストを使用している場合は、 CollectionAssert.IsSubsetOf メソッド:
CollectionAssert.IsSubsetOf(subset, superset);
上記の場合、これは次のことを意味します:
CollectionAssert.IsSubsetOf(t2, t1);
@Cameronのソリューション:
public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
return !a.Except(b).Any();
}
使用法:
bool isSubset = t2.IsSubsetOf(t1);
(これは似ていますが、@ Michaelのブログに投稿されたものとまったく同じではありません)
これは、ここに掲載されている他のソリューション、特にトップソリューションよりもはるかに効率的なソリューションです。
bool isSubset = t2.All(elem => t1.Contains(elem));
t1にない要素をt2で見つけることができる場合、t2はt1のサブセットではないことがわかります。この方法の利点は、.Exceptまたは.Intersectを使用するソリューションとは異なり、追加のスペースを割り当てずにすべてインプレースで実行されることです。さらに、このソリューションは、サブセット条件に違反する単一の要素を見つけるとすぐにブレークすることができますが、他の要素は検索を続けます。以下はソリューションの最適な長い形式であり、テストでは上記の省略形のソリューションよりもわずかに高速です。
bool isSubset = true;
foreach (var element in t2) {
if (!t1.Contains(element)) {
isSubset = false;
break;
}
}
すべてのソリューションの基本的なパフォーマンス分析を行いましたが、結果は劇的です。これらの2つのソリューションは、.Except()および.Intersect()ソリューションよりも約100倍高速であり、追加のメモリを使用しません。
@Cameronと@Neilの回答に基づいて、Enumerableクラスと同じ用語を使用する拡張メソッドを作成しました。
/// <summary>
/// Determines whether a sequence contains the specified elements by using the default equality comparer.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="source">A sequence in which to locate the values.</param>
/// <param name="values">The values to locate in the sequence.</param>
/// <returns>true if the source sequence contains elements that have the specified values; otherwise, false.</returns>
public static bool ContainsAll<TSource>(this IEnumerable<TSource> source, IEnumerable<TSource> values)
{
return !values.Except(source).Any();
}
ここでは、親リスト(つまり
t1
)に含まれていない子リスト(つまりt2
)に要素があるかどうかをチェックします。そのようなものが存在する場合、リストは他のサブセットです
eg:
bool isSubset = !(t2.Any(x => !t1.Contains(x)));
これを試してください
static bool IsSubSet<A>(A[] set, A[] toCheck) {
return set.Length == (toCheck.Intersect(set)).Count();
}
ここでの考え方は、Intersectは両方の配列にある値のみを返すということです。この時点で、結果セットの長さが元のセットと同じ場合、「セット」内のすべての要素は「チェック」にもあります;したがって、「設定」は、「toCheck」のサブセットです
注:&quot; set&quot;の場合、ソリューションは機能しません。重複しています。他の人の投票を盗みたくないので、変更しません。
ヒント:キャメロンの答えに投票しました。