क्या गो के पास "अगर x" है तो वह पायथन के समान है?


289

संपूर्ण सरणी पर पुनरावृति के बिना , यदि मैं xगो का उपयोग कर रहा हूं, तो मैं कैसे जांच सकता हूं ? क्या भाषा का निर्माण होता है?

अजगर की तरह: if "x" in array: ...


2
के शिकार हो सकता है stackoverflow.com/q/8307478/180100

7
AFAIK, वहाँ जाने के लिए आशुलिपि नहीं है। आंतरिक रूप से, अजगर भी सरणी पर पुनरावृत्त होता है, इसके आसपास कोई नहीं होता है।
डेनिश 94

6
BTW, इस के लिए एक महत्वपूर्ण नोट यह है कि ऐसा करने का कोई तरीका नहीं है (जैसा कि आप पूछते हैं) " [w] पूरे सरणी पर पुनरावृत्ति करना"। इस तरह के छोरों को स्पष्ट करना (या किसी फ़ंक्शन के पीछे जैसे strings.Index) यह कोड को क्या कर रहा है, इसे और अधिक स्पष्ट बनाने में मदद करता है। मुझे यह आभास मिलता है कि शायद आपको लगता है कि पायथन in array:कुछ तेज / जादू कर रहा है। AFAIK यह नहीं है लूप को स्पष्ट करने से लेखक (और सभी पाठकों) को जागरूक करने और अन्य कार्यान्वयन (उदाहरण के लिए एक नक्शा) पर विचार करने में मदद मिलती है।
डेव सी

5
हालांकि, अगर सेट में "x" वास्तव में बहुत तेज है।
रॉबर्टो अलसीना

6
मुझे नहीं लगता कि हम एक कार्यक्रम के लिए तेजी से दृष्टिकोण पूछ रहे हैं, हम सिर्फ एक संक्षिप्त के लिए पूछ रहे हैं (और अभी भी नहीं मिला है ...)
मिगवेल

जवाबों:


340

गो में इसे करने के लिए कोई अंतर्निहित ऑपरेटर नहीं है। आपको सरणी पर पुनरावृति करने की आवश्यकता है। आप इसे करने के लिए अपना कार्य लिख सकते हैं, जैसे:

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

यदि आप पूरी सूची पर ध्यान दिए बिना सदस्यता की जांच करना चाहते हैं, तो आपको इस तरह से किसी सरणी या स्लाइस के बजाय मानचित्र का उपयोग करने की आवश्यकता है:

visitedURL := map[string]bool {
    "http://www.google.com": true,
    "https://paypal.com": true,
}
if visitedURL[thisSite] {
    fmt.Println("Already been here.")
}

4
क्या कोई प्रकार निर्दिष्ट किए बिना ऐसा करने का कोई तरीका है? मान लीजिए कि अगर मैं हर सामान्य प्रकार के लिए अलग तरीकों के बिना सिर्फ एक सामान्य सुईइन्हैस्टैक (सुई, हैस्टैक) फ़ंक्शन चाहता हूं
एलन

25
यह प्रतिबिंबित पैकेज के साथ किया जा सकता है, लेकिन यह काफी अक्षम होगा (शायद उतना ही धीमा होगा जितना कि आपने इसे पायथन जैसी गतिशील भाषा में लिखा है)। इसके अलावा, नहीं। लोगों का यही मतलब है कि जब वे कहते हैं कि गो में जेनरिक नहीं है।
andyahholm

2
किसी को भी इस जवाब पर ठोकर खाई है कि आप नक्शे को हल नहीं कर सकते हैं। जाने के नक्शे का उपयोग करने के लिए बड़ा नकारात्मक।
राइजिंगसून

4
आप जावास्क्रिप्ट में भी मैप्स (ऑब्जेक्ट्स) सॉर्ट नहीं कर सकते। यह एक v8 बग है जो ऑब्जेक्ट्स को वर्णानुक्रम में क्रमबद्ध क्रम में मान लौटाता है।
कुमारहेश

7
अधिकांश भाषाओं में मानचित्रों को क्रमबद्ध नहीं किया जाता है - यह मानचित्र डेटा संरचना (हैशमप) के लिए समान है।
हज्जाजमैन

100

एक अन्य समाधान यदि सूची में स्थिर मूल्य हैं।

उदाहरण के लिए: मान्य मानों की सूची से मान्य मूल्य की जाँच:

func IsValidCategory(category string) bool {
    switch category {
    case
        "auto",
        "news",
        "sport",
        "music":
        return true
    }
    return false
}

11
हाँ, क्या होगा यदि आपका "वैध मूल्य" डेटाबेस से आता है?
रामी दबैन

हाँ, यह साफ-सुथरा है लेकिन केवल तभी जब इन मूल्यों को पहले से परिभाषित किया जा सकता है।
सूअर का बच्चा

2
@ रोनडेजेरो तब मैं इसका इस्तेमाल कर सकता था: myValue IN (उपकुंजी) :)
ऐलेक

3
यह शीर्ष उत्तर की तुलना में नीट है
सूअर का बच्चा

50

यह पुस्तक "गो में प्रोग्रामिंग: 21 वीं सदी के लिए अनुप्रयोग बनाना" से उद्धरण है:

इस तरह के एक सरल रेखीय खोज का उपयोग करना अनसोल्ड डेटा के लिए एकमात्र विकल्प है और छोटी स्लाइस (सैकड़ों वस्तुओं तक) के लिए ठीक है। लेकिन बड़े स्लाइसों के लिए- खासकर अगर हम बार-बार खोजों का प्रदर्शन कर रहे हैं- रैखिक खोज बहुत ही अक्षम है, औसतन हर बार आधे सामान की तुलना करने की आवश्यकता होती है।

गो एक सॉर्ट (खोज) विधि प्रदान करता है जो बाइनरी सर्च एल्गोरिथ्म का उपयोग करता है: इसके लिए हर बार केवल लॉग 2 (एन) आइटम (जहां एन आइटम की संख्या है) की तुलना की आवश्यकता होती है। इसे परिप्रेक्ष्य में रखने के लिए, 1000000 वस्तुओं की एक रेखीय खोज के लिए औसतन 500000 तुलनाओं की आवश्यकता होती है, जिसमें सबसे खराब स्थिति 1000000 तुलनाओं की होती है; सबसे खराब स्थिति में भी बाइनरी सर्च को सबसे अधिक 20 तुलनाओं की जरूरत है।

files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.Search(len(files),
    func(i int) bool { return files[i] >= target })
if i < len(files) && files[i] == target {
    fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}

https://play.golang.org/p/UIndYQ8FeW


10
यह केवल तभी समझ में आता है जब आप बार-बार खोज करते हैं। अन्यथा आपको सॉर्ट और बाइनरी खोज के लिए जटिलता एन * लॉग (एन) * लॉग (एन), बनाम रैखिक खोज के लिए बस एन है।
क्रिश्चियन

1
यह वास्तव में सिर्फ है n*log(n) + log(n), क्योंकि यह दो स्वतंत्र स्वतंत्र संचालन हैं
pomo_mondreganto

27

सॉर्ट का उपयोग करने वाला उपरोक्त उदाहरण करीब है, लेकिन स्ट्रिंग्स के मामले में बस SearchString का उपयोग करें:

files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.SearchStrings(files, target)
if i < len(files) && files[i] == target {
    fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}

https://golang.org/pkg/sort/#SearchStrings


2
यह उत्तर नीचे दिए गए उत्तर की कम जानकारीपूर्ण कॉपी पेस्ट जैसा दिखता है, जो इस उत्तर से पहले हुआ था।
साइटिनस

@cytinus आप किस उत्तर का उल्लेख कर रहे हैं? केवल एक ही है जिसे मैं आधारित देखता हूं sort.SearchStrings
अकिम

1
मुझे एक बड़े स्लाइस के माध्यम से दोहराया खोजों पर 100x स्पीडअप मिला।
Xeoncross

20

बस इसी तरह का सवाल था और इस थ्रेड में कुछ सुझावों को आज़माने का फैसला किया।

मैंने 3 प्रकार के लुकअप के सर्वश्रेष्ठ और सबसे खराब मामलों को देखा है:

  • मानचित्र का उपयोग करना
  • एक सूची का उपयोग कर
  • स्विच स्टेटमेंट का उपयोग करना

यहाँ एक फ़ंक्शन कोड है:

func belongsToMap(lookup string) bool {
list := map[string]bool{
    "900898296857": true,
    "900898302052": true,
    "900898296492": true,
    "900898296850": true,
    "900898296703": true,
    "900898296633": true,
    "900898296613": true,
    "900898296615": true,
    "900898296620": true,
    "900898296636": true,
}
if _, ok := list[lookup]; ok {
    return true
} else {
    return false
}
}


func belongsToList(lookup string) bool {
list := []string{
    "900898296857",
    "900898302052",
    "900898296492",
    "900898296850",
    "900898296703",
    "900898296633",
    "900898296613",
    "900898296615",
    "900898296620",
    "900898296636",
}
for _, val := range list {
    if val == lookup {
        return true
    }
}
return false
}

func belongsToSwitch(lookup string) bool {
switch lookup {
case
    "900898296857",
    "900898302052",
    "900898296492",
    "900898296850",
    "900898296703",
    "900898296633",
    "900898296613",
    "900898296615",
    "900898296620",
    "900898296636":
    return true
}
return false
}

सर्वश्रेष्ठ मामले परिदृश्य सूची में पहला आइटम चुनते हैं, सबसे खराब स्थिति कोई भी शून्य मान का उपयोग नहीं करता है।

यहाँ परिणाम हैं:

BenchmarkBelongsToMapWorstCase-4 2000000 787 ns/op BenchmarkBelongsToSwitchWorstCase-4 2000000000 0.35 ns/op BenchmarkBelongsToListWorstCase-4 100000000 14.7 ns/op BenchmarkBelongsToMapBestCase-4 2000000 683 ns/op BenchmarkBelongsToSwitchBestCase-4 100000000 10.6 ns/op BenchmarkBelongsToListBestCase-4 100000000 10.4 ns/op

स्विच सभी तरह से जीतता है, सबसे खराब स्थिति सबसे अच्छे मामले की तुलना में सबसे तेज है। नक्शे सबसे खराब हैं और सूची स्विच करने के करीब है।

इसलिए नैतिक है: यदि आपके पास एक स्थिर, यथोचित छोटी सूची है, तो स्विच स्टेटमेंट जाने का रास्ता है।


मुझे नहीं पता कि क्या गो इस मामले का अनुकूलन करता है, लेकिन क्या इससे कोई फर्क पड़ता है कि क्या आप परीक्षण फ़ंक्शन के बाहर सूची / मानचित्र के इनिशियलाइज़ेशन को स्थानांतरित करते हैं?
w00t

मैं यह देखने के लिए उत्सुक हूं कि तुलना एक क्रमबद्ध सूची के साथ कैसे होगी और क्या यह इसके लायक होगा
माइकल ड्रेपर

स्विच स्टेटमेंट के :बजाय इसके बारे में क्या ,? क्या यह इसे तेज करता है?
थॉमस सॉवाजन

मैंने caseएक ही मामले के बजाय कई बयानों का उपयोग करने की कोशिश की । परिणाम समझदारी से दोनों कार्यों के साथ समान हैं।
थॉमस सॉवाजन

7

एक अन्य विकल्प सेट के रूप में मानचित्र का उपयोग कर रहा है। आप बस कुंजियों का उपयोग करते हैं और मूल्य एक बूलियन की तरह कुछ होना चाहिए जो हमेशा सच होता है। फिर आप आसानी से देख सकते हैं कि नक्शे में कुंजी है या नहीं। यदि आपको सेट के व्यवहार की आवश्यकता है, तो यह उपयोगी है, जहां यदि आप एक मूल्य को कई बार जोड़ते हैं तो यह केवल एक बार सेट में है।

यहां एक सरल उदाहरण है जहां मैं नक्शे में चाबियाँ के रूप में यादृच्छिक संख्याएं जोड़ता हूं। यदि एक ही संख्या एक बार से अधिक उत्पन्न नहीं होती है तो कोई बात नहीं, यह केवल एक बार अंतिम नक्शे में दिखाई देगा। तब मैं एक साधारण का उपयोग करता हूं अगर यह देखने के लिए जांचें कि क्या एक कुंजी नक्शे में है या नहीं।

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    var MAX int = 10

    m := make(map[int]bool)

    for i := 0; i <= MAX; i++ {
        m[rand.Intn(MAX)] = true
    }

    for i := 0; i <= MAX; i++ {
        if _, ok := m[i]; ok {
            fmt.Printf("%v is in map\n", i)
        } else {
            fmt.Printf("%v is not in map\n", i)
        }
    }
}

यहाँ यह खेल के मैदान पर है


0

यह उतना ही करीब है जितना कि मैं पायथन के "इन" ऑपरेटर के प्राकृतिक अनुभव को प्राप्त कर सकता हूं। आपको अपने खुद के प्रकार को परिभाषित करना होगा। फिर आप "है" की तरह एक विधि जोड़कर उस प्रकार की कार्यक्षमता को बढ़ा सकते हैं जो आप की तरह व्यवहार करता है।

package main

import "fmt"

type StrSlice []string

func (list StrSlice) Has(a string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

func main() {
    var testList = StrSlice{"The", "big", "dog", "has", "fleas"}

    if testList.Has("dog") {
        fmt.Println("Yay!")
    }
}

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

हां, यह रैखिक समय में चलता है, लेकिन यह बात नहीं है। बिंदु यह पूछना और सीखना है कि सामान्य भाषा में गो क्या है और क्या नहीं है। यह एक अच्छा व्यायाम है। चाहे यह उत्तर मूर्खतापूर्ण हो या उपयोगी, पाठक के ऊपर निर्भर है।

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