2013-03-10 10 views
153

なし配列全体の反復どのようにしてGoで配列の 'x'がチェックできますか? PythonのようなGolangはPythonに似た "if x in"構造を持っていますか?

if "x" in array: ...

+2

http://stackoverflow.com/q/8307478/180100 –

+4

のデュープ私の知る限り、外出先でそのための速記はありませんことがございます。内部的には、Pythonも配列を反復処理しますが、それを回避することはできません。 – Danish94

+3

ところで、重要なことは、*あなたが求めているように、* ** [w] ithout **が配列全体を反復処理する*方法がないということです。このようなループを明示的に(あるいは 'strings.Index'のような関数の背後に)作ることは、コードが何をしているのかをより明白にするのに役立ちます。おそらくあなたはPythonの「配列内」が速い/魔法のようなことをしていると思っているような印象を受けます。 AFAIKそうではありません。ループを明示的にすることは、ライター(およびすべての読者)に、他の実装(例えば、地図)を認識させ、考慮させるのに役立つ。 –

答えて

197

移動でそれを行うには、組み込みの演算子がありません。配列全体を反復処理する必要があります。あなたは全体のリストを反復処理することなく、会員資格を確認することができるようにしたい場合は、マップの代わりに、配列またはスライスを使用する必要が

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.") 
} 
+1

タイプを指定せずにこれを行う方法はありますか?私はちょうど一般的なneedleInHaystack(needle、haystack)関数を各タイプ毎に別々のメソッドなしにしたいとしましょう。 – Allen

+9

これはリフレクトパッケージで行うことができますが、かなり効率が悪いでしょう(おそらく、 Pythonのような動的言語)。それ以外は、いいえ。 Goはジェネリック医薬品を持っていないと言うと、それは人々が意味するものです。 – andybalholm

+1

この回答を見つけた人は、地図を並べ替えることはできません。ゴーマップを使うことには大きな欠点があります。 – khuderm

34

これは本からの引用である、これはソートされていない データのための唯一の選択肢であるように、単純な線形検索を使用して

:「ゴーでのプログラミング:21世紀のためのアプリケーションの作成」 a小さなスライス(数百項目まで)ではうまくいきます。しかし、 大きなスライス、特に検索を繰り返している場合は、 線形検索は非常に効率が悪く、毎回平均して項目の半分を比較する必要があります。

移動バイナリサーチ アルゴリズムを使用sort.Search()メソッドを提供する:これはLOG2(N)項目(N 項目の数である)、各時間の比較を必要とします。これを視野に入れるために、 の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

+2

これは、繰り返し検索する場合にのみ意味があります。それ以外の場合は、ソートとバイナリ検索ではn * log(n)* log(n)の複雑さがあります。 – christian

40

リストは、静的な値が含まれている場合、別の解決策。

例:有効な値のリストから有効な値のチェック:

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

ええ、もしあなたの「有効な値」がデータベースから来たら? –

14

上記の例で使用したソートは近いですが、文字列の場合には、単に検索文字列を使用します。

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

+0

この回答は、この回答の前に起こった、以下の回答のあまり有益ではないコピー貼り付けのように見えます。 – cytinus

+0

@cytinusどのような答えを言いますか?それは 'sort.SearchStrings'に基づいて私が見る唯一のものです。 – akim

+0

大きなスライスを繰り返して検索すると、100倍のスピードアップが得られます。 – Xeoncross

5

もう1つのオプションは、マップをセットとして使用しています。あなたはキーだけを使用し、値は常に真であるブール値のようなものにします。次に、マップにキーが含まれているかどうかを簡単に確認できます。これは、セットの動作を必要とする場合に便利です。値を複数回追加すると、セット内に1回だけ追加されます。

ここでは、マップに乱数をキーとして追加する簡単な例を示します。同じ番号が2回以上生成されてもそれは問題ではありませんが、最終的なマップには一度しか表示されません。次に、キーが地図にあるかどうかを調べるために単純なifを使用します。

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

Here it is on the go playground

関連する問題