C # में सरणियों की तुलना करने का सबसे आसान तरीका


180

जावा में, Arrays.equals()दो बुनियादी सरणियों की सामग्री की आसानी से तुलना करने की अनुमति देता है (सभी मूल प्रकारों के लिए अधिभार उपलब्ध हैं)।

क्या C # में ऐसी कोई बात है? क्या सी # में दो सरणियों की सामग्री की तुलना करने का कोई "जादू" है?


1
टैग में '.net' जोड़ा गया क्योंकि इस तकनीक का उपयोग अन्य समान .net आधारित भाषाओं में किया जा सकता है।
इवान प्लाइस

3
इसे पढ़ने वाले सभी के लिए, ध्यान रखें कि स्वीकृत उत्तर SequenceEqual का उपयोग कर रहा है। SequenceEqual न केवल यह जाँचता है कि क्या उनके पास समान डेटा है, बल्कि यदि वे समान क्रम में समान डेटा रखते हैं
John Demetriou

जवाबों:


262

आप उपयोग कर सकते हैं Enumerable.SequenceEqual। यह किसी भी के लिए काम करता है IEnumerable<T>, न कि केवल सरणियाँ।


यह केवल तभी काम करता है जब वे एक ही क्रम में हों
जॉन डेमेट्रियौ

1
SequenceEqualएक अच्छा विकल्प प्रदर्शन बुद्धिमान नहीं हो सकता है, क्योंकि इसका वर्तमान कार्यान्वयन पूरी तरह से अपने स्रोतों में से एक की गणना कर सकता है यदि वे केवल लंबाई से भिन्न होते हैं। सरणियों के साथ, हम Lengthपहले समानता की जांच कर सकते हैं , ताकि अंत में फील्डिंग करने के लिए अलग-अलग लंबाई के सरणियों से बचने के लिए false
फ्रेडरिक

72

का प्रयोग करें Enumerable.SequenceEqualमें 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

1
ध्यान रखें कि यह अशक्त तर्कों के लिए फेंकता है, इसलिए यह सुनिश्चित न करें किnew int[] {1}.SequenceEquals(null) == false
सारा

30

इसके अलावा arrays (और tuples) के लिए आप .NET 4.0 से नए इंटरफेस का उपयोग कर सकते हैं: IStructuralComparable और IStructuralEquatable । उनका उपयोग करके आप न केवल सरणियों की समानता की जांच कर सकते हैं, बल्कि उनकी तुलना भी कर सकते हैं।

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
}

मुझे क्षमा करें, क्या यह एक 1 या 0 होना चाहिए a.StructuralCompare(b)?
मफू

बड़े मूल्य प्रकार के सरणियों पर, इनका उपयोग करने में एक प्रदर्शन हिट होता है, क्योंकि उनका वर्तमान कार्यान्वयन तुलना करने के लिए प्रत्येक मूल्य को बॉक्स करेगा।
फ्रेडेरिक

18

के लिए .NET 4.0 और उच्च आप उपयोग कर के माध्यम से सरणी में तत्वों या tuples तुलना कर सकते हैं StructuralComparisons के प्रकार:

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

संपादित करें: बहुत जल्द बोला गया। क्या मैं IStructuralComparable के साथ StructualEqualityCompare कर सकता हूं? मैं तुलना करने के लिए वस्तुओं के दो सरणियों के साथ तुलना करना चाहता हूं ताकि पता चल सके कि कौन "पहले" आता है। मैंने IStructuralComparable se1 = a1 की कोशिश की; Console.WriteLine (se1.CompareTo (a2, संरचनात्मकComparison.StructuralEqualityComparer)); प्राप्त करना: 'System.Collections.IEqualityComparer' से 'System.Collections.IComparer'
shindigo

1
ठीक - सही कॉल है: IStructuralComparable se1 = a1; Console.WriteLine (se1.CompareTo (a2, स्ट्रक्चरल कॉमपेरिसन। SructuralComparer));
shindigo

15

SequenceEqual केवल दो शर्तों या मिलने पर ही वापस लौटेगा।

  1. इनमें समान तत्व होते हैं।
  2. तत्व एक ही क्रम में हैं।

यदि आप केवल यह जांचना चाहते हैं कि क्या उनके आदेश की परवाह किए बिना समान तत्व हैं और आपकी समस्या प्रकार की है

क्या values2 में values1 में निहित सभी मूल्य शामिल हैं?

आप 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);

आपको अलग परिणाम मिलेंगे।

मेरे मामले में मेरे पास एक सरणी की एक स्थानीय प्रतिलिपि है और यह जांचना चाहता हूं कि क्या मूल सरणी से कुछ भी हटा दिया गया है, इसलिए मैं इस पद्धति का उपयोग करता हूं।


2
विभिन्न क्रमों में समान मान रखने वाली सारणियां, केवल EQUAL नहीं हैं। क्या आप 'डेमेट्रियौ' == 'यूओर्टेमेडी' कहते हैं?
edc65

वह निर्भर करता है। यदि आप सरणियों को अनियंत्रित संग्रह के रूप में उपयोग कर रहे हैं और केवल यह जाँचने की आवश्यकता है कि उनमें समान तत्व हैं (जैसे, किसी विन्यास सूची के विरुद्ध डेटाबेस से मान), तो यह सबसे आसान तरीका है जो मैंने पाया है। यदि ऑर्डर मायने रखता है (जैसे, एक स्ट्रिंग), तो आप उपयोग करेंगे SequenceEqual
आर्मंडो

11

यूनिट परीक्षणों के लिए, आप CollectionAssert.AreEqualइसके बजाय उपयोग कर सकते हैं Assert.AreEqual

यह शायद सबसे आसान तरीका है।


11

यदि आप 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;
        return array1.Count() == array2.Count() && !array1.Except(array2).Any();
    }
}

परीक्षण कोड इस तरह दिखता है:

class Program
{
    static void Main(string[] args)
    {
        int[] a1 = new int[] { 1, 2, 3 };
        int[] a2 = new int[] { 3, 2, 1 };
        int[] a3 = new int[] { 1, 3 };
        int[] a4 = null;
        int[] a5 = null;
        int[] a6 = new int[0];

        Console.WriteLine(a1.ItemsEqual(a2)); // Output: True.
        Console.WriteLine(a2.ItemsEqual(a3)); // Output: False.
        Console.WriteLine(a4.ItemsEqual(a5)); // Output: True. No Exception.
        Console.WriteLine(a4.ItemsEqual(a3)); // Output: False. No Exception.
        Console.WriteLine(a5.ItemsEqual(a6)); // Output: False. No Exception.
    }
}

यह मेरे लिए मददगार था, लेकिन अगर a1 = { 1, 1 }और a2 = { 1, 2 }फिर, पहला परीक्षण गलत परिणाम देता है। वापसी कथन होना चाहिएreturn array1.Count() == array2.Count() && !array1.Except(array2).Any() && !array2.Except(array1).Any();
पोलशिएंट

2

कुछ अनुप्रयोगों के लिए बेहतर हो सकता है:

string.Join(",", arr1) == string.Join(",", arr2)

2

यह LINQ समाधान काम करता है, यह सुनिश्चित नहीं करता है कि यह SequenceEquals के प्रदर्शन में तुलना कैसे करता है। लेकिन यह अलग-अलग सरणी लंबाई को संभालता है और। सभी पहले आइटम पर बाहर निकल जाएंगे जो पूरे सरणी के माध्यम से पुनरावृत्ति किए बिना समान नहीं है।

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

1

तत्व की तुलना? किस बारे में

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 नमूनों से दो उदाहरणों को जोड़ती है )


1
यह विभिन्न लंबाई के सरणियों ( गलत तरीके से उपज सकता है true) और nullसरणियों (दुर्घटना नहीं होगी ) को संभालता है ।
Frédéric

1

मैंने इसे दृश्य स्टूडियो में किया और इसने पूरी तरह से काम किया; इस कोड के साथ इंडेक्स द्वारा एरेज़ इंडेक्स की तुलना करना।

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 हैं


2
यह अलग-अलग लंबाई (दुर्घटनाग्रस्त हो जाएगा) की सरणियों को संभाल नहीं करता है, nullसरणियों (भी दुर्घटनाग्रस्त हो जाएगा), और यह ओपी द्वारा पूछे जाने पर कुछ और करता है। उन्होंने केवल समानता को जानने के लिए कहा, गिनती के बिना कि कितने आइटम अलग हैं या मेल खाते हैं।
फ्रैडरिक

0

सरणी समानता को मानने का अर्थ है कि दोनों सरणियों में समान अनुक्रमित पर समान तत्व हैं, SequenceEqualउत्तर और IStructuralEquatableउत्तर है

लेकिन दोनों में कमियां हैं, प्रदर्शन बुद्धिमान है।

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] != second[i])
            return false;
    }
    return true;
}

लेकिन निश्चित रूप से, यह सरणी समानता की जाँच के कुछ "जादू का रास्ता" नहीं है।

तो वर्तमान में, नहीं, वास्तव Arrays.equals()में जावा में .net के बराबर नहीं है ।


क्या पहला और दूसरा दोनों सही परिणाम नहीं होगा? null == null, है ना?
जेसी विलियम्स

1
यदि दोनों हैं तो पहला परीक्षण सही लौटेगा null। तुम्हारा मतलब क्या है?
Frédéric

1
अगर (पहला [i]! = दूसरा [i]) जेनरिक के साथ काम नहीं करेगा। आपको (यदि (पहले [i]। इक्वल्स (दूसरा [i])) का उपयोग करना होगा।
जैक ग्रिफिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.