यदि दो संरचनाएं, स्लाइस या मानचित्र समान हैं तो तुलना कैसे करें?


131

मैं जांचना चाहता हूं कि क्या दो संरचनाएं, स्लाइस और मानचित्र समान हैं।

लेकिन मैं निम्नलिखित कोड के साथ समस्याओं में चल रहा हूं। संबंधित लाइनों पर मेरी टिप्पणी देखें।

package main

import (
    "fmt"
    "reflect"
)

type T struct {
    X int
    Y string
    Z []int
    M map[string]int
}

func main() {
    t1 := T{
        X: 1,
        Y: "lei",
        Z: []int{1, 2, 3},
        M: map[string]int{
            "a": 1,
            "b": 2,
        },
    }

    t2 := T{
        X: 1,
        Y: "lei",
        Z: []int{1, 2, 3},
        M: map[string]int{
            "a": 1,
            "b": 2,
        },
    }

    fmt.Println(t2 == t1)
    //error - invalid operation: t2 == t1 (struct containing []int cannot be compared)

    fmt.Println(reflect.ValueOf(t2) == reflect.ValueOf(t1))
    //false
    fmt.Println(reflect.TypeOf(t2) == reflect.TypeOf(t1))
    //true

    //Update: slice or map
    a1 := []int{1, 2, 3, 4}
    a2 := []int{1, 2, 3, 4}

    fmt.Println(a1 == a2)
    //invalid operation: a1 == a2 (slice can only be compared to nil)

    m1 := map[string]int{
        "a": 1,
        "b": 2,
    }
    m2 := map[string]int{
        "a": 1,
        "b": 2,
    }
    fmt.Println(m1 == m2)
    // m1 == m2 (map can only be compared to nil)
}

http://play.golang.org/p/AZIzW2WunI


कोन्सिडर ने 'अमान्य संचालन: t2 == t1 (संरचना युक्त नक्शा [स्ट्रिंग] int की तुलना नहीं की जा सकती)', यह तब होता है यदि संरचना में कोई int [] उसकी परिभाषा के भीतर नहीं है
विक्टर

जवाबों:


157

आप प्रतिबिंबित का उपयोग कर सकते हैं। डीपक्वेल , या आप अपने स्वयं के फ़ंक्शन को लागू कर सकते हैं (जो प्रदर्शन बुद्धिमान प्रतिबिंब का उपयोग करने से बेहतर होगा):

http://play.golang.org/p/CPdfsYGNy_

m1 := map[string]int{   
    "a":1,
    "b":2,
}
m2 := map[string]int{   
    "a":1,
    "b":2,
}
fmt.Println(reflect.DeepEqual(m1, m2))

69

reflect.DeepEqual अक्सर आपके प्रश्न के अनुसार, दो तरह की संरचनाओं की तुलना करने के लिए गलत तरीके से उपयोग किया जाता है।

cmp.Equal संरचना की तुलना के लिए एक बेहतर उपकरण है।

यह देखने के लिए कि प्रतिबिंब की सलाह क्यों दी गई है, आइए दस्तावेज़ीकरण देखें :

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

....

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

यदि हम time.Timeएक ही यूटीसी समय के दो मूल्यों की तुलना करते हैं, t1 == t2तो उनके मेटाडेटा का समय अलग होने पर गलत होगा।

go-cmpEqual()विधि की तलाश करता है और सही समय की तुलना करने के लिए इसका उपयोग करता है।

उदाहरण:

m1 := map[string]int{
    "a": 1,
    "b": 2,
}
m2 := map[string]int{
    "a": 1,
    "b": 2,
}
fmt.Println(cmp.Equal(m1, m2)) // will result in true

9
हाँ बिल्कुल! परीक्षण लिखते समय, इसका उपयोग करना बहुत महत्वपूर्ण है go-cmpऔर नहीं reflect
केविन मिन्हार्ट

दुर्भाग्य से न तो प्रतिबिंबित और न ही सीएमपी एक संरचना की ओर संकेत के साथ एक संरचना की तुलना करने के लिए काम करते हैं। यह अभी भी चाहता है कि संकेत समान हों।
वायोमैन

2
@GeneralLeeSpeaking यह सच नहीं है। से सीएमपी प्रलेखन : "अगर वे बात अंतर्निहित मूल्यों भी बराबर होते हैं करने के लिए प्वाइंटर बराबर हैं"
इलिया Choly

Cmp दस्तावेज़ीकरण के अनुसार , cmp का उपयोग केवल परीक्षण लिखते समय करने की सलाह दी जाती है, क्योंकि अगर वस्तु तुलनीय नहीं है तो यह घबराहट हो सकती है।
मार्टिन

17

यहां बताया गया है कि आप अपना स्वयं का फ़ंक्शन http://play.golang.org/p/Qgw7XuLNhb कैसे रोल करेंगे

func compare(a, b T) bool {
  if &a == &b {
    return true
  }
  if a.X != b.X || a.Y != b.Y {
    return false
  }
  if len(a.Z) != len(b.Z) || len(a.M) != len(b.M) {
    return false
  }
  for i, v := range a.Z {
    if b.Z[i] != v {
      return false
    }
  }
  for k, v := range a.M {
    if b.M[k] != v {
      return false
    }
  }
  return true
}

3
मैं जोड़ने की सलाह if len(a.Z) != len(b.Z) || len(a.M) != len(b.M) { return false }दूंगा, क्योंकि उनमें से एक अतिरिक्त क्षेत्र हो सकता है।
OneOfOne

सभी संरचनात्मक जानकारी संकलन समय पर जानी जाती है। यह शर्म की बात है कि कंपाइलर इस भारी उठाने को किसी तरह से नहीं कर सकता है।
रिक -777

3
@ रिक -777 स्लाइस के लिए कोई तुलना नहीं है। इस तरह से भाषा डिजाइनर इसे चाहते थे। सरल पूर्णांकों की तुलना में यह कहना आसान नहीं है। यदि वे समान क्रम में समान तत्व रखते हैं तो क्या स्लाइस समान हैं? लेकिन क्या होगा अगर उनकी क्षमता भिन्न हो? आदि
जस्टिन

1
if & a == & b {return true} यह कभी भी सही का मूल्यांकन नहीं करेगा यदि तुलना करने वाले पैरामीटर को मान से पास किया जा रहा है।
सीन

4

के बाद से जुलाई 2017 आप उपयोग कर सकते हैं cmp.Equalके साथ cmpopts.IgnoreFieldsविकल्प।

func TestPerson(t *testing.T) {
    type person struct {
        ID   int
        Name string
    }

    p1 := person{ID: 1, Name: "john doe"}
    p2 := person{ID: 2, Name: "john doe"}
    println(cmp.Equal(p1, p2))
    println(cmp.Equal(p1, p2, cmpopts.IgnoreFields(person{}, "ID")))

    // Prints:
    // false
    // true
}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.