C#에서 어레이를 비교하는 가장 쉬운 방법
자바에서는,Arrays.equals()
두 개의 기본 배열의 내용을 쉽게 비교할 수 있습니다(모든 기본 유형에 대해 사용 가능).
C#에 그런 것이 있습니까?C#에서 두 배열의 내용을 비교할 수 있는 "마법적인" 방법이 있습니까?
당신은 할 수 있습니다.이 기능은 모든 사용자에게 적합합니다.IEnumerable<T>
어레이뿐만이 아닙니다.
LINQ에서 사용합니다.
int[] arr1 = new int[] { 1,2,3};
int[] arr2 = new int[] { 3,2,1 };
Console.WriteLine(arr1.SequenceEqual(arr2)); // false
Console.WriteLine(arr1.Reverse().SequenceEqual(arr2)); // true
어레이(및 튜플)의 경우에도 .NET 4.0: I Structural Comparable 및 I StructuralEquatable의 새 인터페이스를 사용할 수 있습니다.이를 사용하면 배열의 동일성을 확인할 수 있을 뿐만 아니라 비교할 수도 있습니다.
static class StructuralExtensions
{
public static bool StructuralEquals<T>(this T a, T b)
where T : IStructuralEquatable
{
return a.Equals(b, StructuralComparisons.StructuralEqualityComparer);
}
public static int StructuralCompare<T>(this T a, T b)
where T : IStructuralComparable
{
return a.CompareTo(b, StructuralComparisons.StructuralComparer);
}
}
{
var a = new[] { 1, 2, 3 };
var b = new[] { 1, 2, 3 };
Console.WriteLine(a.Equals(b)); // False
Console.WriteLine(a.StructuralEquals(b)); // True
}
{
var a = new[] { 1, 3, 3 };
var b = new[] { 1, 2, 3 };
Console.WriteLine(a.StructuralCompare(b)); // 1
}
SequenceEqual
두 가지 조건이 충족되거나 충족된 경우에만 true가 반환됩니다.
- 동일한 요소를 포함합니다.
- 요소의 순서가 동일합니다.
주문에 관계없이 동일한 요소가 포함되어 있는지 여부만 확인하고 싶은 경우 문제가 유형입니다.
value2가 value1에 포함된 모든 값을 포함합니까?
LINQ 방법 LINQ를 할 수 .Enumerable.Except
결과에 값이 있는지 확인합니다.예가 .
int[] values1 = { 1, 2, 3, 4 };
int[] values2 = { 1, 2, 5 };
var result = values1.Except(values2);
if(result.Count()==0)
{
//They are the same
}
else
{
//They are different
}
그리고 이것을 사용함으로써 다른 아이템들도 자동으로 얻을 수 있습니다.일석이조.
만약 당신이 코드를 이렇게 실행한다면, 명심하세요.
var result = values2.Except(values1);
당신은 다른 결과를 얻을 것입니다.
제 경우에는 배열의 로컬 복사본이 있는데 원래 배열에서 제거된 항목이 있는지 확인하고 싶어서 이 방법을 사용합니다.
.NET 4.0 이상의 경우 구조 비교 유형을 사용하여 배열 또는 튜플의 요소를 비교할 수 있습니다.
object[] a1 = { "string", 123, true };
object[] a2 = { "string", 123, true };
Console.WriteLine (a1 == a2); // False (because arrays is reference types)
Console.WriteLine (a1.Equals (a2)); // False (because arrays is reference types)
IStructuralEquatable se1 = a1;
//Next returns True
Console.WriteLine (se1.Equals (a2, StructuralComparisons.StructuralEqualityComparer));
당신이 처리하고 싶다면,null
입력은 우아하게 하고 항목 순서는 무시하고 다음 솔루션을 사용해 보십시오.
static class Extensions
{
public static bool ItemsEqual<TSource>(this TSource[] array1, TSource[] array2)
{
if (array1 == null && array2 == null)
return true;
if (array1 == null || array2 == null)
return false;
if (array1.Count() != array2.Count())
return false;
return !array1.Except(array2).Any() && !array2.Except(array1).Any();
}
}
테스트 코드는 다음과 같습니다.
public static void Main()
{
int[] a1 = new int[] { 1, 2, 3 };
int[] a2 = new int[] { 3, 2, 1 };
int[] a3 = new int[] { 1, 3 };
Console.WriteLine(a1.ItemsEqual(a2)); // Output: True.
Console.WriteLine(a2.ItemsEqual(a3)); // Output: False.
Console.WriteLine(a3.ItemsEqual(a2)); // Output: False.
int[] a4 = new int[] { 1, 1 };
int[] a5 = new int[] { 1, 2 };
Console.WriteLine(a4.ItemsEqual(a5)); // Output: False
Console.WriteLine(a5.ItemsEqual(a4)); // Output: False
int[] a6 = null;
int[] a7 = null;
int[] a8 = new int[0];
Console.WriteLine(a6.ItemsEqual(a7)); // Output: True. No Exception.
Console.WriteLine(a8.ItemsEqual(a6)); // Output: False. No Exception.
Console.WriteLine(a7.ItemsEqual(a8)); // Output: False. No Exception.
}
단위 검정의 경우 다음을 사용할 수 있습니다.CollectionAssert.AreEqual
에 Assert.AreEqual
.
그것이 아마도 가장 쉬운 방법일 것입니다.
일부 애플리케이션의 경우 다음과 같은 이점이 있습니다.
string.Join(",", arr1) == string.Join(",", arr2)
배열이 동일하다는 것은 두 배열이 동일한 인덱스에서 동일한 요소를 갖는다는 것을 의미한다고 가정하면 정답과 정답이 있습니다.
하지만 둘 다 성능 면에서 단점이 있습니다.
SequenceEqual
에서의 때 각하여 그 중할 수 있습니다.NetFramework는 배열의 길이가 다를 때 바로 가기를 사용하지 않으므로 각 요소를 비교하여 그 중 하나를 전체적으로 열거할 수 있습니다.
이것은 에 따라 다릅니다.순 맛(예: .).Net5), 단축될 수 있습니다. 이 설명을 참조하십시오.그래서 최신 정보를 위해서요.넷 프로젝트,SequenceEqual
좋은 선택이 되어야 합니다.
IStructuralEquatable
일반적이지 않으며 각 비교 값의 복싱을 유발할 수 있습니다.게다가 그것은 사용하기가 매우 간단하지 않고 이미 그것을 숨기는 몇몇 도우미 방법을 코딩해야 합니다.
다음과 같은 것을 사용하는 것이 성능 면에서 더 나을 수 있습니다.
bool ArrayEquals<T>(T[] first, T[] second)
{
if (first == second)
return true;
if (first == null || second == null)
return false;
if (first.Length != second.Length)
return false;
for (var i = 0; i < first.Length; i++)
{
if (!first[i].Equals(second[i]))
return false;
}
return true;
}
하지만 물론, 이것은 배열 동일성을 확인하는 "마법적인 방법"은 아닙니다.
그래서 현재, 아니요, 실제로 자바와 동등한 것은 없습니다.Arrays.equals()
네트.
이 LINQ 솔루션은 작동하지만 Sequence Equals와 성능이 어떻게 비교되는지는 잘 모르겠습니다.그러나 다른 배열 길이 및 를 처리합니다.전체 배열을 반복하지 않고 동일하지 않은 첫 번째 항목에서 모두 종료됩니다.
private static bool arraysEqual<T>(IList<T> arr1, IList<T> arr2)
=>
ReferenceEquals(arr1, arr2) || (
arr1 != null && arr2 != null &&
arr1.Count == arr2.Count &&
arr1.Select((a, i) => arr2[i].Equals(a)).All(i => i)
);
요소적으로 비교? 어때요?
public void Linq78a()
{
int[] numbers1 = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
bool bb = numbers.Zip(numbers1, (a, b) => (a == b)).Any(p => !p);
if (!bb) Console.WriteLine("Lists are equal (bb)");
else Console.WriteLine("Lists are not equal (bb)");
}
(a==b) 조건을 a와 b에서 비교할 항목으로 대체합니다.
(MSDN 개발자 Linq 샘플의 두 가지 예를 결합한 것입니다.)
저는 비주얼 스튜디오에서 이것을 했고 완벽하게 작동했습니다. 인덱스별 배열과 이 코드를 짧게 비교했습니다.
private void compareButton_Click(object sender, EventArgs e)
{
int[] answer = { 1, 3, 4, 6, 8, 9, 5, 4, 0, 6 };
int[] exam = { 1, 2, 3, 6, 8, 9, 5, 4, 0, 7 };
int correctAnswers = 0;
int wrongAnswers = 0;
for (int index = 0; index < answer.Length; index++)
{
if (answer[index] == exam[index])
{
correctAnswers += 1;
}
else
{
wrongAnswers += 1;
}
}
outputLabel.Text = ("The matching numbers are " + correctAnswers +
"\n" + "The non matching numbers are " + wrongAnswers);
}
출력은 다음과 같습니다. 일치하는 숫자는 7입니다. 일치하지 않는 숫자는 3입니다.
사용할 수 있습니다.Enumerable.Intersect
:
int[] array1 = new int[] { 1, 2, 3, 4,5 },
array2 = new int[] {7,8};
if (array1.Intersect(array2).Any())
Console.WriteLine("matched");
else
Console.WriteLine("not matched");
저는 두 세트가 어떤 순서로든 같은 내용을 가지고 있는지 확인하려고 했습니다., 각 두 값을 것입니다. 즉, 집 A의 합 각 대 모 집 두 에 서 두 값 해 가 요 의 소 수 의 다 가 것 합 니 미 같 는 을 다 진 을 당 합 해 에 소 요 ▁that ▁with ▁a , 집 ▁of 즉 ▁in ▁sets 의 ▁that ▁there ▁numbers ▁were ▁set ▁in ▁meant ▁value 다 합 ▁for ▁equal ,중복 항목을 설명하고 싶었습니다(그래서{1,2,2,3}
그리고.{1,2,3,3}
"동일"로 간주해서는 안 됩니다.
이것이 제가 생각해 낸 것입니다(IsNullOrEmpty는 열거형이 null이거나 요소가 0인 경우 true를 반환하는 또 다른 정적 확장 메서드입니다).
public static bool HasSameContentsAs<T>(this IEnumerable<T> source, IEnumerable<T> target)
where T : IComparable
{
//If our source is null or empty, then it's just a matter of whether or not the target is too
if (source.IsNullOrEmpty())
return target.IsNullOrEmpty();
//Otherwise, if the target is null/emtpy, they can't be equal
if (target.IsNullOrEmpty())
return false;
//Neither is null or empty, so we'll compare contents. To account for multiples of
//a given value (ex. 1,2,2,3 and 1,1,2,3 are not equal) we'll group the first set
foreach (var group in source.GroupBy(s => s))
{
//If there are a different number of elements in the target set, they don't match
if (target.Count(t => t.Equals(group.Key)) != group.Count())
return false;
}
//If we got this far, they have the same contents
return true;
}
사용할 수도 있습니다.array1.ToList().All(x => array2.Contains(x))
가 동일하지 아배을 비야하 는경우 해교동 열닌서가▁which경
주문을 비교하고 싶지 않지만 null 값 처리를 포함하여 각 항목의 개수를 비교하려면 확장 방법을 작성했습니다.
예를 들어 다음과 같은 결과를 제공합니다.
new int?[]{ }.IgnoreOrderComparison(new int?{ }); // true
new int?[]{ 1 }.IgnoreOrderComparison(new int?{ }); // false
new int?[]{ }.IgnoreOrderComparison(new int?{ 1 }); // false
new int?[]{ 1 }.IgnoreOrderComparison(new int?{ 1 }); // true
new int?[]{ 1, 2 }.IgnoreOrderComparison(new int?{ 2, 1 }); // true
new int?[]{ 1, 2, null }.IgnoreOrderComparison(new int?{ 2, 1 }); // false
new int?[]{ 1, 2, null }.IgnoreOrderComparison(new int?{ null, 2, 1 }); // true
new int?[]{ 1, 2, null, null }.IgnoreOrderComparison(new int?{ null, 2, 1 }); // false
new int?[]{ 2 }.IgnoreOrderComparison(new int?{ 2, 2 }); // false
new int?[]{ 2, 2 }.IgnoreOrderComparison(new int?{ 2, 2 }); // true
코드는 다음과 같습니다.
public static class ArrayComparisonExtensions
{
public static bool IgnoreOrderComparison<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) =>
IgnoreOrderComparison(first, second, EqualityComparer<TSource>.Default);
public static bool IgnoreOrderComparison<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
var a = ToDictionary(first, out var firstNullCount);
var b = ToDictionary(second, out var secondNullCount);
if (a.Count != b.Count)
return false;
if (firstNullCount != secondNullCount)
return false;
foreach (var item in a)
{
if (b.TryGetValue(item.Key, out var count) && item.Value == count)
continue;
return false;
}
return true;
Dictionary<TSource, int> ToDictionary(IEnumerable<TSource> items, out int nullCount)
{
nullCount = 0;
var result = new Dictionary<TSource, int>(comparer);
foreach (var item in items)
{
if (item is null)
nullCount++;
else if (result.TryGetValue(item, out var count))
result[item] = count + 1;
else
result[item] = 1;
}
return result;
}
}
}
각 열거형을 한 번만 열거하지만 각 열거형에 대한 사전을 만들고 이러한 사전도 한 번 반복합니다.저는 이것을 개선할 수 있는 방법에 관심이 있습니다.
배열 중 하나를 다음으로 변환하는 이 스레드에 대한 답을 확인합니다.HashSet
및용을 합니다.SetEquals
다른 배열과 비교할 수 있습니다.그러나 이렇게 하면 주문 또는 중복이 확인되지 않습니다.
목록 패턴은 C#11에 추가되었습니다.네트 7 RC2.
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
Console.WriteLine(numbers is [1, 2, 4]); // False
int[] a = { 2, 1, 3, 4, 5, 2 };
int[] b = { 2, 1, 3, 4, 5, 2 };
bool ans = true;
if(a.Length != b.Length)
{
ans = false;
}
else
{
for (int i = 0; i < a.Length; i++)
{
if( a[i] != b[i])
{
ans = false;
}
}
}
string str = "";
if(ans == true)
{
str = "Two Arrays are Equal";
}
if (ans == false)
{
str = "Two Arrays are not Equal";
}
//--------------Or You can write One line of Code-------------
var ArrayEquals = a.SequenceEqual(b); // returns true
언급URL : https://stackoverflow.com/questions/3232744/easiest-way-to-compare-arrays-in-c-sharp
'programing' 카테고리의 다른 글
bash에 공백 없이 16진수 문자만 포함된 파일의 16진수 덤프를 만드는 방법은 무엇입니까? (0) | 2023.05.19 |
---|---|
VB.NET의 정수에 아무것도 할당할 수 없는 이유는 무엇입니까? (0) | 2023.05.19 |
SQLite 데이터베이스에 한 번에 여러 행을 삽입할 수 있습니까? (0) | 2023.05.19 |
Python: 동일한 Excel 파일에 이미지 및 데이터 프레임 쓰기 (0) | 2023.05.19 |
내포된 f-스트링 (0) | 2023.05.19 |