web-dev-qa-db-ja.com

配列が別の配列のサブセットであるかどうかを確認します

そのリストが別のリストのサブセットであるかどうかを確認する方法についてのアイデアはありますか?

具体的には、私は持っています

List<double> t1 = new List<double> { 1, 3, 5 };
List<double> t2 = new List<double> { 1, 5 };

LINQを使用して、t2がt1のサブセットであることを確認するにはどうすればよいですか?

137
Graviton
bool isSubset = !t2.Except(t1).Any();
242

セットを使用する場合は、リストの代わりに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のソリューションは、存在する繰り返し要素を削除する必要があるという警告に対応します。

56
tvanfosson

unit-testingの場合、 CollectionAssert.IsSubsetOf メソッドも利用できます:

CollectionAssert.IsSubsetOf(subset, superset);

上記の場合、これは次のことを意味します。

CollectionAssert.IsSubsetOf(t2, t1);
11
Géza

拡張メソッドとしての@Cameronのソリューション:

public static bool IsSubsetOf<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    return !a.Except(b).Any();
}

使用法:

bool isSubset = t2.IsSubsetOf(t1);

(これは似ていますが、@ Michaelのブログに投稿されたものとまったく同じではありません)

6
Neil

これは、ここに掲載されている他のソリューション、特にトップソリューションよりもはるかに効率的なソリューションです。

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倍高速であり、追加のメモリを使用しません。

6
user2325458

@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();
}
0
sclarke81

ここでは、子リストに要素が存在するかどうかを確認します(つまり、t2)親リストに含まれていない(つまりt1)。そのようなものが存在しない場合、リストは他のサブセットです

例えば:

bool isSubset = !(t2.Any(x => !t1.Contains(x)));
0
Lucifer