जवाबों:
मुस्तफा ने पहले ही बताया है कि इस तरह की विधि लिखने के लिए तुच्छ है, और mkb ने आपको सॉर्ट पैकेज से द्विआधारी खोज का उपयोग करने का संकेत दिया। लेकिन अगर आप बहुत सारे ऐसे चेक करने जा रहे हैं, तो आप इसके बजाय एक मैप का उपयोग करने पर भी विचार कर सकते हैं।
यह जांचना तुच्छ है कि क्या एक विशेष मानचित्र कुंजी value, ok := yourmap[key]
मुहावरे का उपयोग करके मौजूद है । चूंकि आप मूल्य में दिलचस्पी नहीं रखते हैं, आप map[string]struct{}
उदाहरण के लिए भी बना सकते हैं । struct{}
यहां खाली का उपयोग करने से यह फायदा होता है कि इसके लिए किसी अतिरिक्त स्थान की आवश्यकता नहीं होती है और गो का आंतरिक मानचित्र प्रकार उस प्रकार के मूल्यों के लिए अनुकूलित होता है। इसलिए, map[string] struct{}
गो दुनिया में सेट के लिए एक लोकप्रिय विकल्प है।
struct{}{}
खाली संरचना का मूल्य प्राप्त करने के लिए लिखना है ताकि आप इसे अपने मानचित्र में पास कर सकें जब आप एक तत्व जोड़ना चाहते हैं। बस इसे आज़माएं, और यदि आपको कोई समस्या आती है, तो बेझिझक पूछें। यदि आप को समझना आसान है (जब तक आपके पास भारी मात्रा में डेटा नहीं है) तो आप मुस्तफा के समाधान का भी उपयोग कर सकते हैं।
map[string] bool
के साथ तुलना करें map[string] struct{}
। map[string] struct{}
एक हैक की तरह लगता है विशेष रूप से एक खाली संरचना को शुरूstruct {}{}
नहीं, ऐसी विधि मौजूद नहीं है, लेकिन लिखने के लिए तुच्छ है:
func contains(s []int, e int) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
आप नक्शे का उपयोग कर सकते हैं यदि वह लुकअप आपके कोड का एक महत्वपूर्ण हिस्सा है, लेकिन नक्शे में लागत भी है।
interface{}
यदि स्लाइस को सॉर्ट किया जाता है, तो sort
पैकेज में कार्यान्वित एक द्विआधारी खोज होती है ।
एक का उपयोग करने के बजाय slice
, map
एक बेहतर समाधान हो सकता है।
सरल उदाहरण:
package main
import "fmt"
func contains(slice []string, item string) bool {
set := make(map[string]struct{}, len(slice))
for _, s := range slice {
set[s] = struct{}{}
}
_, ok := set[item]
return ok
}
func main() {
s := []string{"a", "b"}
s1 := "a"
fmt.Println(contains(s, s1))
}
sliceToMap
जो सभी तैयारी करता है। उसके बाद, नक्शे को क्वेरी करना तुच्छ और कुशल है।
प्रकार पैकेज का निर्माण ब्लॉकों प्रदान करता है अगर आपके टुकड़ा क्रमबद्ध है या आप इसे सुलझाने के लिए तैयार हैं।
input := []string{"bird", "apple", "ocean", "fork", "anchor"}
sort.Strings(input)
fmt.Println(contains(input, "apple")) // true
fmt.Println(contains(input, "grow")) // false
...
func contains(s []string, searchterm string) bool {
i := sort.SearchStrings(s, searchterm)
return i < len(s) && s[i] == searchterm
}
SearchString
वापस करने का वादा करता है the index to insert x if x is not present (it could be len(a))
, इसलिए उस की एक जांच से पता चलता है कि क्या स्ट्रिंग को छांटा गया है।
O(n)
और यह समाधान इसे बनाता है O(n*log(n))
।
contains
हैं O(log(n))
, लेकिन समग्र दृष्टिकोण O(n*log(n))
सॉर्ट के कारण है।
आप ऐसे इंटरफ़ेस पर पुनरावृति करने के लिए प्रतिबिंबित पैकेज का उपयोग कर सकते हैं जिसका ठोस प्रकार एक टुकड़ा है:
func HasElem(s interface{}, elem interface{}) bool {
arrV := reflect.ValueOf(s)
if arrV.Kind() == reflect.Slice {
for i := 0; i < arrV.Len(); i++ {
// XXX - panics if slice element points to an unexported struct field
// see https://golang.org/pkg/reflect/#Value.Interface
if arrV.Index(i).Interface() == elem {
return true
}
}
}
return false
}
यदि किसी कुंजी के आधार पर वस्तुओं को खोजने के लिए मानचित्र का उपयोग करना संभव नहीं है, तो आप गॉडेरिव टूल पर विचार कर सकते हैं । Goderive में एक विधि का विशिष्ट प्रकार का कार्यान्वयन उत्पन्न होता है, जो आपके कोड को पठनीय और कुशल बनाता है।
उदाहरण;
type Foo struct {
Field1 string
Field2 int
}
func Test(m Foo) bool {
var allItems []Foo
return deriveContainsFoo(allItems, m)
}
DeriveContainsFoo विधि उत्पन्न करने के लिए:
go get -u github.com/awalterschulze/goderive
goderive ./...
अपने कार्यक्षेत्र फ़ोल्डर में चलाएँयह विधि deriveContains के लिए बनाई जाएगी:
func deriveContainsFoo(list []Foo, item Foo) bool {
for _, v := range list {
if v == item {
return true
}
}
return false
}
गोदरिव में एक कार्यात्मक प्रोग्रामिंग शैली को लागू करने के लिए कुछ अन्य उपयोगी सहायक विधियों के लिए समर्थन है।
func Contain(target interface{}, list interface{}) (bool, int) {
if reflect.TypeOf(list).Kind() == reflect.Slice || reflect.TypeOf(list).Kind() == reflect.Array {
listvalue := reflect.ValueOf(list)
for i := 0; i < listvalue.Len(); i++ {
if target == listvalue.Index(i).Interface() {
return true, i
}
}
}
if reflect.TypeOf(target).Kind() == reflect.String && reflect.TypeOf(list).Kind() == reflect.String {
return strings.Contains(list.(string), target.(string)), strings.Index(list.(string), target.(string))
}
return false, -1
}
सुनिश्चित नहीं हैं कि यहां जेनरिक की जरूरत है। आपको बस अपने वांछित व्यवहार के लिए एक अनुबंध की आवश्यकता है। यदि आप अपनी वस्तुओं को संग्रह में स्वयं व्यवहार करना चाहते हैं, तो उदाहरण के लिए इक्वलस () और गेटहैशकोड () उदाहरणों से आगे निकलकर, अन्य भाषाओं में आपको जो करना है, उससे अधिक नहीं है।
type Identifiable interface{
GetIdentity() string
}
func IsIdentical(this Identifiable, that Identifiable) bool{
return (&this == &that) || (this.GetIdentity() == that.GetIdentity())
}
func contains(s []Identifiable, e Identifiable) bool {
for _, a := range s {
if IsIdentical(a,e) {
return true
}
}
return false
}
Contains()
में लागू किया गया है List<T>
, इसलिए आपको केवल Equals()
उस काम के लिए ही लागू करना होगा।
मैंने इन उत्तरों से समाधान के साथ एक बहुत ही सरल बेंचमार्क बनाया।
https://gist.github.com/NorbertFenk/7bed6760198800207e84f141c41d93c7
यह वास्तविक बेंचमार्क नहीं है क्योंकि शुरू में, मैंने बहुत सारे तत्व नहीं डाले हैं, लेकिन कांटे और इसे बदलने के लिए स्वतंत्र महसूस करते हैं।
इसे थोड़ा 'हैकी' माना जा सकता है, लेकिन स्लाइस के आकार और सामग्री के आधार पर, आप स्लाइस को एक साथ जोड़ सकते हैं और एक स्ट्रिंग खोज कर सकते हैं।
उदाहरण के लिए आपके पास एक स्लाइस है जिसमें एकल शब्द मान हैं (जैसे "हाँ", "नहीं", "हो सकता है")। इन परिणामों को एक स्लाइस से जोड़ा जाता है। यदि आप जांचना चाहते हैं कि क्या इस स्लाइस में कोई "शायद" परिणाम है, तो आप उपयोग कर सकते हैं
exSlice := ["yes", "no", "yes", "maybe"]
if strings.Contains(strings.Join(exSlice, ","), "maybe") {
fmt.Println("We have a maybe!")
}
यह कितना उपयुक्त है यह वास्तव में इसके सदस्यों के स्लाइस और लंबाई के आकार पर निर्भर करता है। बड़े स्लाइस या लंबे मूल्यों के लिए प्रदर्शन या उपयुक्तता के मुद्दे हो सकते हैं, लेकिन परिमित आकार के छोटे स्लाइस और सरल मूल्यों के लिए यह वांछित परिणाम प्राप्त करने के लिए एक वैध एक लाइनर है।
exSlice := ["yes and no", "maybe", "maybe another"]
","+strings.Join(exSlice,",")+","
और",maybe,"
गो स्टाइल:
func Contains(n int, match func(i int) bool) bool {
for i := 0; i < n; i++ {
if match(i) {
return true
}
}
return false
}
s := []string{"a", "b", "c", "o"}
// test if s contains "o"
ok := Contains(len(s), func(i int) bool {
return s[i] == "o"
})