it-source

어레이가 다른 어레이의 서브셋인지 확인합니다.

criticalcode 2023. 4. 21. 21:00
반응형

어레이가 다른 어레이의 서브셋인지 확인합니다.

그 리스트가 다른 리스트의 서브셋인지 어떻게 확인할 수 있는지 아세요?

특히, 저는

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();

세트를 사용할 경우 List 대신 HashSet을 사용합니다.다음으로 IsSubset Of()를 사용할 수 있습니다.

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

bool isSubset = t2.IsSubsetOf(t1);

LINQ를 사용하지 않아 죄송합니다. :- (

목록을 사용해야 하는 경우 @Jared의 솔루션은 반복된 요소를 모두 제거해야 한다는 경고와 함께 작동합니다.

이는 여기에 게재되어 있는 다른 솔루션, 특히 상위 솔루션보다 훨씬 효율적인 솔루션입니다.

bool isSubset = t2.All(elem => t1.Contains(elem));

t2에서 t1에 없는 단일 원소를 찾을 수 있다면 t2는 t1의 부분 집합이 아니라는 것을 알 수 있습니다.이 방법의 장점은 를 사용하는 솔루션과는 달리 추가 공간을 할당하지 않고 모두 일괄적으로 수행된다는 것입니다.또는 제외.교차하다.또한 이 솔루션은 서브셋 조건을 위반하는 단일 요소를 발견하면 즉시 중단될 수 있으며 다른 요소는 검색을 계속할 수 있습니다.아래는 최적의 긴 형태의 솔루션으로, 위의 속기 솔루션보다 테스트 속도가 약간 더 빠릅니다.

bool isSubset = true;
foreach (var element in t2) {
    if (!t1.Contains(element)) {
        isSubset = false;
        break;
    }
}

모든 솔루션의 기본적인 퍼포먼스 분석을 실시했는데, 그 결과는 극단적입니다.이들 2개의 솔루션은 의 약 100배 고속입니다.예외()와cross() 솔루션을 사용하고 추가 메모리를 사용하지 않습니다.

유닛 테스트의 경우는, Collection Assert 를 사용할 수도 있습니다.IsSubset Of 메서드:

CollectionAssert.IsSubsetOf(subset, superset);

위의 경우 이는 다음을 의미합니다.

CollectionAssert.IsSubsetOf(t2, t1);

이 답변에서는 BenchmarkDotNet을 사용하여 3가지 실제 솔루션을 벤치마킹했습니다.

  • !t2.Except(t1).Any()예외()를 호출했습니다.임의의()
  • t2.IsSubsetOf(t1)해시 세트라는 이름의
  • t2.All(elem => t1.Contains(elem))모두 호출(=> 포함)

3가지 파라미터가 있습니다.

  • 슈퍼셋 수
  • 부분집합 길이
  • 항목의 변동성

모든 상위 집합이 임의 길이이며 범위에 포함된 항목입니다.[0; Variability). 서브셋은 길이가 일정하고 범위 내 아이템이 포함되어 있다.[0; Variability).

승자는 All(=> Contains) 메서드입니다.HashSet을 사용하는 경우보다 최대 30배, Except()보다 최대 50배 빠를 수 있습니다.임의의().

코드는 github에서 찾을 수 있습니다.

업데이트 @Gert Arnold의 코멘트에서 언급한 바와 같이 벤치마크에 버그가 있습니다.전화해봤어요.ToHashSet()모든 반복의 내부.그래서 저는 또한 사전 빌드된 해시셋 컬렉션을 만들고, 다음과 같은 이름의 순수 해시셋 테스트를 추가했습니다.prebuilt HashSet도 한다.All(=>Contains)인 것 .슈퍼셋의 가변성(및 중복성)이 포인트인 것 같습니다.값의 변동성이 낮으면 해시 집합이 데이터에서 제거되므로 해시 집합이 승리합니다.

마지막 표는 다음과 같습니다.

|             Method | SupersetsInIteration | SubsetLength | Variability |          Mean |        Error |       StdDev |        Median |
|------------------- |--------------------- |------------- |------------ |--------------:|-------------:|-------------:|--------------:|
|     Except().Any() |                 1000 |           10 |         100 |   1,485.89 μs |     7.363 μs |     6.887 μs |   1,488.36 μs |
|        ToHashSet() |                 1000 |           10 |         100 |   1,015.59 μs |     5.099 μs |     4.770 μs |   1,015.43 μs |
| prebuilt HashSet   |                 1000 |           10 |         100 |      38.76 μs |     0.065 μs |     0.054 μs |      38.78 μs |
|    All(=>Contains) |                 1000 |           10 |         100 |     105.46 μs |     0.320 μs |     0.267 μs |     105.38 μs |
|     Except().Any() |                 1000 |           10 |       10000 |   1,912.17 μs |    38.180 μs |    87.725 μs |   1,890.72 μs |
|        ToHashSet() |                 1000 |           10 |       10000 |   1,038.70 μs |    20.028 μs |    40.459 μs |   1,019.35 μs |
| prebuilt HashSet   |                 1000 |           10 |       10000 |      28.22 μs |     0.165 μs |     0.155 μs |      28.24 μs |
|    All(=>Contains) |                 1000 |           10 |       10000 |      81.47 μs |     0.117 μs |     0.109 μs |      81.45 μs |
|     Except().Any() |                 1000 |           50 |         100 |   4,888.22 μs |    81.268 μs |    76.019 μs |   4,854.42 μs |
|        ToHashSet() |                 1000 |           50 |         100 |   4,323.23 μs |    21.424 μs |    18.992 μs |   4,315.16 μs |
| prebuilt HashSet   |                 1000 |           50 |         100 |     186.53 μs |     1.257 μs |     1.176 μs |     186.35 μs |
|    All(=>Contains) |                 1000 |           50 |         100 |   1,173.37 μs |     2.667 μs |     2.227 μs |   1,173.08 μs |
|     Except().Any() |                 1000 |           50 |       10000 |   7,148.22 μs |    20.545 μs |    19.218 μs |   7,138.22 μs |
|        ToHashSet() |                 1000 |           50 |       10000 |   4,576.69 μs |    20.955 μs |    17.499 μs |   4,574.34 μs |
| prebuilt HashSet   |                 1000 |           50 |       10000 |      33.87 μs |     0.160 μs |     0.142 μs |      33.85 μs |
|    All(=>Contains) |                 1000 |           50 |       10000 |     131.34 μs |     0.569 μs |     0.475 μs |     131.24 μs |
|     Except().Any() |                10000 |           10 |         100 |  14,798.42 μs |   120.423 μs |   112.643 μs |  14,775.43 μs |
|        ToHashSet() |                10000 |           10 |         100 |  10,263.52 μs |    64.082 μs |    59.942 μs |  10,265.58 μs |
| prebuilt HashSet   |                10000 |           10 |         100 |   1,241.19 μs |     4.248 μs |     3.973 μs |   1,241.75 μs |
|    All(=>Contains) |                10000 |           10 |         100 |   1,058.41 μs |     6.766 μs |     6.329 μs |   1,059.22 μs |
|     Except().Any() |                10000 |           10 |       10000 |  16,318.65 μs |    97.878 μs |    91.555 μs |  16,310.02 μs |
|        ToHashSet() |                10000 |           10 |       10000 |  10,393.23 μs |    68.236 μs |    63.828 μs |  10,386.27 μs |
| prebuilt HashSet   |                10000 |           10 |       10000 |   1,087.21 μs |     2.812 μs |     2.631 μs |   1,085.89 μs |
|    All(=>Contains) |                10000 |           10 |       10000 |     847.88 μs |     1.536 μs |     1.436 μs |     847.34 μs |
|     Except().Any() |                10000 |           50 |         100 |  48,257.76 μs |   232.573 μs |   181.578 μs |  48,236.31 μs |
|        ToHashSet() |                10000 |           50 |         100 |  43,938.46 μs |   994.200 μs | 2,687.877 μs |  42,877.97 μs |
| prebuilt HashSet   |                10000 |           50 |         100 |   4,634.98 μs |    16.757 μs |    15.675 μs |   4,643.17 μs |
|    All(=>Contains) |                10000 |           50 |         100 |  10,256.62 μs |    26.440 μs |    24.732 μs |  10,243.34 μs |
|     Except().Any() |                10000 |           50 |       10000 |  73,192.15 μs |   479.584 μs |   425.139 μs |  73,077.26 μs |
|        ToHashSet() |                10000 |           50 |       10000 |  45,880.72 μs |   141.497 μs |   125.433 μs |  45,860.50 μs |
| prebuilt HashSet   |                10000 |           50 |       10000 |   1,620.61 μs |     3.507 μs |     3.280 μs |   1,620.52 μs |
|    All(=>Contains) |                10000 |           50 |       10000 |   1,460.01 μs |     1.819 μs |     1.702 μs |   1,459.49 μs |
|     Except().Any() |               100000 |           10 |         100 | 149,047.91 μs | 1,696.388 μs | 1,586.803 μs | 149,063.20 μs |
|        ToHashSet() |               100000 |           10 |         100 | 100,657.74 μs |   150.890 μs |   117.805 μs | 100,654.39 μs |
| prebuilt HashSet   |               100000 |           10 |         100 |  12,753.33 μs |    17.257 μs |    15.298 μs |  12,749.85 μs |
|    All(=>Contains) |               100000 |           10 |         100 |  11,238.79 μs |    54.228 μs |    50.725 μs |  11,247.03 μs |
|     Except().Any() |               100000 |           10 |       10000 | 163,277.55 μs | 1,096.107 μs | 1,025.299 μs | 163,556.98 μs |
|        ToHashSet() |               100000 |           10 |       10000 |  99,927.78 μs |   403.811 μs |   337.201 μs |  99,812.12 μs |
| prebuilt HashSet   |               100000 |           10 |       10000 |  11,671.99 μs |     6.753 μs |     5.986 μs |  11,672.28 μs |
|    All(=>Contains) |               100000 |           10 |       10000 |   8,217.51 μs |    67.959 μs |    56.749 μs |   8,225.85 μs |
|     Except().Any() |               100000 |           50 |         100 | 493,925.76 μs | 2,169.048 μs | 1,922.805 μs | 493,386.70 μs |
|        ToHashSet() |               100000 |           50 |         100 | 432,214.15 μs | 1,261.673 μs | 1,180.169 μs | 431,624.50 μs |
| prebuilt HashSet   |               100000 |           50 |         100 |  49,593.29 μs |    75.300 μs |    66.751 μs |  49,598.45 μs |
|    All(=>Contains) |               100000 |           50 |         100 |  98,662.71 μs |   119.057 μs |   111.366 μs |  98,656.00 μs |
|     Except().Any() |               100000 |           50 |       10000 | 733,526.81 μs | 8,728.516 μs | 8,164.659 μs | 733,455.20 μs |
|        ToHashSet() |               100000 |           50 |       10000 | 460,166.27 μs | 7,227.011 μs | 6,760.150 μs | 457,359.70 μs |
| prebuilt HashSet   |               100000 |           50 |       10000 |  17,443.96 μs |    10.839 μs |     9.608 μs |  17,443.40 μs |
|    All(=>Contains) |               100000 |           50 |       10000 |  14,222.31 μs |    47.090 μs |    44.048 μs |  14,217.94 μs |

@Cameron의 솔루션 확장 방법:

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

사용방법:

bool isSubset = t2.IsSubsetOf(t1);

(이것은 비슷하지만, @Michael의 블로그에 게재된 것과 전혀 다릅니다.)

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

2개의 2개의 배열이 .array1 ★★★★★★★★★★★★★★★★★」array2 것을 하려고 합니다.array1은 값에 있습니다.array2:

array1.All(ar1 => array2.Any(ar2 => ar2.Equals(ar1)));

★★★★★★ar2.Equals(ar1)평등을 다른 방법으로 설명할 경우 대체할 수 있습니다.

이거 드셔보세요

static bool IsSubSet<A>(A[] set, A[] toCheck) {
  return set.Length == (toCheck.Intersect(set)).Count();
}

여기서의 개념은 교차점은 두 배열 모두에 있는 값만 반환한다는 것입니다.이 시점에서 결과 집합의 길이가 원래 집합과 동일한 경우 "set"의 모든 요소도 "check"에 있으므로 "set"은 "to Check"의 하위 집합입니다.

메모: "set"에 중복이 있으면 솔루션이 작동하지 않습니다.다른 사람의 표를 뺏고 싶지 않아서 바꾸는 게 아니에요.

힌트: 나는 카메론의 대답에 투표했다.

에서는 자목록에합니다( 자목록에 요소가 존재하는지 합니다).t2부모 「」)에 포함되지 않습니다( 「」( 「」).t1하지 않는 는,

예:

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

언급URL : https://stackoverflow.com/questions/332973/check-whether-an-array-is-a-subset-of-another

반응형