दो स्लाइस की समानता की जाँच करना


274

अगर दो स्लाइस बराबर हैं तो मैं कैसे जांच सकता हूं?


111
प्रश्न वास्तव में एक सरल कार्य के बारे में है, लेकिन IMO यह एक वास्तविक प्रश्न है, जिसमें एक बहुत ही विशिष्ट उत्तर है। यह कैसे "एक वास्तविक प्रश्न नहीं" के रूप में बंद किया जा सकता था, जहां तक ​​मैं देख सकता हूं, जिन लोगों को मैं कभी भी टैग किए गए प्रश्नों में सक्रिय होने की याद नहीं दिला सकता हूं, वह मेरे से परे है। विशेष रूप से: प्रश्न गैर अस्पष्ट, पूर्ण, एकल (हालांकि सरल) समस्या के लिए संकीर्ण है, गैर बयानबाजी और इसके वर्तमान रूप में सटीक और सटीक उत्तर दिया जा सकता है। ==ऑपरेटर केवल कुछ प्रकार के लिए जाओ में परिभाषित किया गया है, तो इसके अलावा, इस सवाल का भी एक वैध एक है।
zzzz

4
फिर भी, यह करीबी कारण में बताई गई चीजों में से कोई भी नहीं है ("इसके वर्तमान रूप में यथोचित उत्तर नहीं दिया जा सकता है")।
रिच चर्चर

9
हाहाहा, मैं विश्वास नहीं कर सकता कि यह "एक वास्तविक प्रश्न नहीं" के लिए बंद हो गया। 1) जो पूछा जा रहा है, उसे बताना मुश्किल नहीं है। 2) प्रश्न अस्पष्ट / अधूरा / व्यापक / अनुचित नहीं है। यह काफी गाली है!
weberc2

5
ऐसा लगता है कि यह वर्तमान में डाउनवोट बटन को गलती करने के लिए बहुत आसान है ("मुझे लगता है कि यह प्रश्न प्रयास नहीं दिखाता है और अच्छी तरह से नहीं पूछा गया है") क्लोज बटन के साथ "(मुझे लगता है कि इसका उत्तर निम्न कारण से नहीं दिया जा सकता है .. । ")। हो सकता है क्योंकि करीबी वोट स्वतंत्र हैं।
कोस

3
हो रहा है गो में विकसित हो रहा है और खिलाफ चला गया है slice can only be compared to nil, और सोच रहा था कि क्या स्लाइस समानता की जांच करने के लिए एक मुहावरेदार तरीका है ... यदि समानता ऑपरेटर भाषा द्वारा परिभाषित नहीं है, तो मुझे सबसे कुशल तरीका पूछना उचित लगता है इसे पूरा करने के लिए। प्रश्न को बंद करने की आवश्यकता नहीं थी
abgordon

जवाबों:


157

आपको स्लाइस और परीक्षण में प्रत्येक तत्व पर लूप करना होगा। स्लाइस के लिए समानता को परिभाषित नहीं किया गया है। हालांकि, एक bytes.Equalफ़ंक्शन है यदि आप प्रकार के मूल्यों की तुलना कर रहे हैं []byte

func testEq(a, b []Type) bool {

    // If one is nil, the other must also be nil.
    if (a == nil) != (b == nil) { 
        return false; 
    }

    if len(a) != len(b) {
        return false
    }

    for i := range a {
        if a[i] != b[i] {
            return false
        }
    }

    return true
}

15
सुझाव: for i, v := range a { if v != b[i] { return false } }
zzzz

19
@zzzz सावधान, यह अलग लंबाई पर विफल हो जाएगा।
FiloSottile

2
यदि तत्व प्रकार == का समर्थन नहीं करता है तो यह काम नहीं करता है। इसके अलावा, IIUC, Go के पास जेनेरिक जैसी कोई चीज नहीं है। इसका मतलब है कि आपको प्रत्येक फ़ंक्शन प्रकार के लिए इस फ़ंक्शन को कॉपी करना होगा जिसे आप समर्थन करना चाहते हैं। यह स्पष्ट रूप से कुछ है जो भाषा के साथ जहाज होना चाहिए। वास्तव में, यह करता है (प्रतिबिंबित के जादू के साथ), और विक्टर जवाब प्रदान करता है। तथ्य यह है कि यह उस उत्तर के ऊपर चुना गया है, और अधिक उच्च मतदान केवल
पागलपन है

5
जब तक पूरी तरह से आवश्यक नहीं है, तब तक एक भाषा के रूप में प्रतिबिंब का उपयोग न करने की सिफारिश की जाती है। हां, इसे प्रत्येक प्रकार के लिए करने की आवश्यकता होगी लेकिन यह आम तौर पर ऐसा कुछ नहीं है जो आप अक्सर करते हैं। इसके अलावा, प्रतिबिंबित करें। डीपक्वाल कुछ ऐसा कर सकता है जिसकी आपको उम्मीद नहीं है जैसे कि दो अलग-अलग पॉइंटर्स समान हैं क्योंकि वे जिस मान को इंगित करते हैं वह बराबर है।
स्टीफन वेनबर्ग

2
@FiloSottile की लंबाई पहले ही जांच ली जाती है, अगर लंबाई अलग-अलग होती है तो लूप केवल पहुंचता है।
14

259

आपको प्रतिबिंबित का उपयोग करना चाहिए। डीपक्वाल ()

डीपक्वाल गो के == ऑपरेटर का एक पुनरावर्ती विश्राम है।

डीपक्वाल रिपोर्ट देता है कि क्या x और y "गहराई से समान हैं," निम्नानुसार परिभाषित हैं। समान मामलों के दो मूल्य गहरे समान हैं यदि निम्न में से एक मामले में लागू होता है। अलग-अलग प्रकार के मान कभी गहरे नहीं होते।

जब उनके संबंधित तत्व समान रूप से गहरे होते हैं, तो एरे मान समान रूप से गहरे होते हैं।

संरचना मूल्य गहरे समान हैं यदि उनके संबंधित क्षेत्र, निर्यात और अस्पष्टीकृत, दोनों समान रूप से गहरे हैं।

यदि दोनों शून्य हैं, तो फ़ंक मान बहुत गहरे हैं; अन्यथा वे गहराई से समान नहीं हैं।

यदि वे गहराई से समान ठोस मान रखते हैं, तो इंटरफ़ेस मान समान रूप से समान हैं।

यदि वे समान मैप ऑब्जेक्ट हैं या यदि उनकी लंबाई समान है और उनकी संबंधित कुंजियाँ (गो समानता का उपयोग करके मिलान की गई हैं) मैप गहराई से बराबर हैं, तो मैप मान समान रूप से समान हैं।

यदि वे Go के == ऑपरेटर का उपयोग कर रहे हैं या वे समान रूप से समान मूल्यों की ओर इशारा करते हैं, तो पॉइंटर मान गहरे समान हैं।

स्लाइस का मान तब गहरा होता है जब निम्न में से सभी सत्य होते हैं: वे दोनों शून्य या दोनों गैर-शून्य होते हैं, उनकी लंबाई समान होती है, और या तो वे एक ही अंतर्निहित सरणी के प्रारंभिक प्रारंभिक प्रवेश की ओर इशारा करते हैं (अर्थात, और x [0] ] == & y [0]) या उनके संबंधित तत्व (लंबाई तक) गहरे समान हैं। ध्यान दें कि एक गैर-शून्य खाली टुकड़ा और एक शून्य टुकड़ा (उदाहरण के लिए, [] बाइट {} और [] बाइट (नील)) गहराई से बराबर नहीं हैं।

अन्य मान - संख्या, बूल, स्ट्रिंग्स और चैनल - गहराई से समान हैं यदि वे गो के == ऑपरेटर का उपयोग करने के बराबर हैं।


13
एक बहुत ही उपयोगी जवाब। सामान्य प्रतिबिंबित पैकेज प्रदर्शन के बावजूद, परीक्षण के मामलों में उपयोग के लिए एक प्रीपैकेडेड डीप समानता समारोह होना बहुत अच्छा है जहां सादगी और शुद्धता सर्वोपरि है।
वीकेपॉइंटर्स

15
मैं सिर्फ एक बेंचमार्क और प्रतिबिंबित करता हूं। डीपक्वाल पाश की तुलना में 150 गुना धीमा है। सिर्फ FYI करें अगर कोई भी उत्पादन में इस पद्धति का उपयोग करना चाहता है।
निकिडेपेन 3

2
यह समान वस्तुओं के साथ बेतरतीब ढंग से क्रमबद्ध स्लाइस की तुलना नहीं करता है :(
हेमंत_नैगी

5
@ Hemant_Negi दो स्लाइस समान नहीं हैं यदि उनके पास अलग ऑर्डर है। यदि आप आदेश की अवहेलना करते हुए दो स्लाइस की समानता की तुलना करना चाहते हैं, तो उन्हें क्रमबद्ध करें और फिर एक स्लाइस से आइटम को एक नक्शे में स्थानांतरित करें, और फिर जांचें कि दूसरे स्लाइस पर प्रत्येक तत्व नक्शे में है। (इसके अलावा सुनिश्चित करें कि उनकी लंबाई समान है)
रोबर्ट 2222

3
रोब गोइक (2011 में) गो में प्रतिबिंब पर, आधिकारिक गो ब्लॉग में लिखते हैं: "यह एक शक्तिशाली उपकरण है जिसका उपयोग देखभाल के साथ किया जाना चाहिए और जब तक कड़ाई से आवश्यक नहीं है, तब तक ब्लॉग " golang.org/laws-of-reflection । मैं स्लाइस की तुलना करने के लिए उत्पादन कोड में प्रतिबिंब का उपयोग नहीं करूंगा। यह लिखने का एक आसान कार्य है। लेकिन ध्यान दें कि इस प्रश्न के चुने हुए उत्तर में भी संभावित खराबी है, इस बात पर निर्भर करता है कि आप उससे किस व्यवहार की उम्मीद करते हैं: यह पता चलेगा कि स्लाइस जो कि इनिशियलाइज़ की गई हैं लेकिन अभी भी लेन 0 पर हैं और कैप 0 उन स्लाइस से मेल नहीं खाती जो घोषित लेकिन आरंभिक नहीं।
19

44

यह सिर्फ प्रतिबिंबित का उपयोग कर उदाहरण है। डीपक्वाल () जो @ विक्टोरDeryagin के उत्तर में दिया गया है।

package main

import (
    "fmt"
    "reflect"
)

func main() {
    a := []int {4,5,6}
    b := []int {4,5,6}
    c := []int {4,5,6,7}

    fmt.Println(reflect.DeepEqual(a, b))
    fmt.Println(reflect.DeepEqual(a, c))

}

परिणाम:

true
false

इसे गो प्लेग्राउंड में आज़माएं


23

यदि आपके पास दो हैं []byte, तो बाइट्स का उपयोग करके उनकी तुलना करें । ईक्वाल । गोलांग प्रलेखन कहता है:

बराबर एक बूलियन रिपोर्टिंग देता है कि क्या ए और बी एक ही लंबाई के हैं और एक ही बाइट्स हैं। शून्य तर्क एक खाली स्लाइस के बराबर है।

उपयोग:

package main

import (
    "fmt"
    "bytes"
)

func main() {
    a := []byte {1,2,3}
    b := []byte {1,2,3}
    c := []byte {1,2,2}

    fmt.Println(bytes.Equal(a, b))
    fmt.Println(bytes.Equal(a, c))
}

यह छपेगा

true
false

यह शीर्ष क्यों नहीं है
lurf jurv

3

और अभी के लिए, यहाँ https://github.com/google/go-cmp जो है

reflect.DeepEqualतुलना करने के लिए एक और अधिक शक्तिशाली और सुरक्षित विकल्प का इरादा है कि क्या दो मूल्य शब्दार्थ समान हैं।

package main

import (
    "fmt"

    "github.com/google/go-cmp/cmp"
)

func main() {
    a := []byte{1, 2, 3}
    b := []byte{1, 2, 3}

    fmt.Println(cmp.Equal(a, b)) // true
}

1

उस स्थिति में जब आप एक परीक्षण लिखने में रुचि रखते हैं, तो github.com/stretchr/testify/assertआपका मित्र है।

फ़ाइल के आरंभ में लाइब्रेरी आयात करें:

import (
    "github.com/stretchr/testify/assert"
)

फिर परीक्षण के अंदर आप करते हैं:


func TestEquality_SomeSlice (t * testing.T) {
    a := []int{1, 2}
    b := []int{2, 1}
    assert.Equal(t, a, b)
}

दी गई त्रुटि होगी:

                Diff:
                --- Expected
                +++ Actual
                @@ -1,4 +1,4 @@
                 ([]int) (len=2) {
                + (int) 1,
                  (int) 2,
                - (int) 2,
                  (int) 1,
Test:           TestEquality_SomeSlice

assert.Equalआंतरिक रूप से उपयोग करता है reflect.DeepEqualजो आपके परीक्षणों को धीमा और अंततः आपकी पाइपलाइन चलाने के लिए कर सकता है।
दीपक साह

@DeepakSah क्या आपके पास प्रदर्शन अंतर के लिए मानक हैं? परीक्षण में मेरे अनुभव के प्रदर्शन में अड़चन बराबर में नहीं है, और आपको महान गुणवत्ता वाले संदेश मिलते हैं जिनकी उत्पादकता में वृद्धि हुई है
गेब्रियल फुरस्टेनहेम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.