2016-06-01 4 views
12

文字列があり、foo_で始まる値を除外したい、または7文字より長い値を除外したいと考えています。Golangの配列から要素を選択するのは、ほとんどの慣用方法ですか?

私は各要素をループし、ifステートメントを実行して途中でスライスに追加できます。しかし、それを達成するための慣用的な、あるいはもっとゴラン様の方法があれば私は興味がありました。

ただ、たとえば、同じことは、あなたがRubyでそれを持っているように、誰ライナーはありません

my_array.select! { |val| val !~ /^foo_/ && val.length <= 7 } 

答えて

15

としてRubyで行われるかもしれないが、ヘルパー関数を使用すると、それはほとんどのように短くすることができます。ここで

は、スライスをループし、当社のヘルパー関数です、と選択して、関数値で撮影した基準を満たすだけの要素を返します。

あなたのタスクこのヘルパー関数を使用して
func choose(ss []string, test func(string) bool) (ret []string) { 
    for _, s := range ss { 
     if test(s) { 
      ret = append(ret, s) 
     } 
    } 
    return 
} 

ss := []string{"foo_1", "asdf", "loooooooong", "nfoo_1", "foo_2"} 

mytest := func(s string) bool { return !strings.HasPrefix(s, "foo_") && len(s) <= 7 } 
s2 := choose(ss, mytest) 

fmt.Println(s2) 

出力(Go Playground上でそれを試してみてください):

[asdf nfoo_1] 

注:多くの要素が選択されることが期待されている場合は

、事前に「ビッグ」retスライスを割り当て、その代わりappend()の単純な代入を使用することが有益であるかもしれません。戻す前に、retを選択した要素の数と同じ長さにスライスします。

ノート#2:私の例では

私は要素が返される場合告げるtest()機能を選択しました。だから私はあなたの "除外"条件を逆転させなければならなかった。明らかに、何を除外すべきかを指示するテスター関数を期待するためのヘルパー関数を書くことができます(何を含めるかではありません)。

+0

ありがとうございました!それは良い方法です。 – user2490003

+1

Upvoteは 'filter'の代わりに' choose'を使用しています。もっと慣れて、 "filter"よりも返すものを "選択"してください。 – Verran

+4

@Verran "choose"は、私にとっては(たぶんランダムに)1つの結果しか示唆していません。しかし、「フィルタ」は、存在するすべての言語とライブラリで、ある条件を明確に視覚化して、あるものを通過させ、他の条件を妨げます。 –

2

Rubyのように1行でGoで同じ結果が得られるという慣用的な方法はありませんが、ヘルパー関数を使用するとRubyと同じ表現力を得ることができます。

あなたは、このヘルパー関数を呼び出すことができます。ここでは

Filter(strs, func(v string) bool { 
    return strings.HasPrefix(v, "foo_") // return foo_testfor 
})) 

が全体のコードです:

package main 

import "strings" 
import "fmt" 

// Returns a new slice containing all strings in the 
// slice that satisfy the predicate `f`. 
func Filter(vs []string, f func(string) bool) []string { 
    vsf := make([]string, 0) 
    for _, v := range vs { 
     if f(v) && len(v) > 7 { 
      vsf = append(vsf, v) 
     } 
    } 
    return vsf 
} 

func main() { 

    var strs = []string{"foo1", "foo2", "foo3", "foo3", "foo_testfor", "_foo"} 

    fmt.Println(Filter(strs, func(v string) bool { 
     return strings.HasPrefix(v, "foo_") // return foo_testfor 
    })) 
} 

し、実行例:Playground

6

robpike's filter libraryを見てください。これは、あなたができるようになる:ロブによってREADME.md

package main 

import (
    "fmt" 
    "strings" 
    "filter" 
) 

func isNoFoo7(a string) bool { 
    return ! strings.HasPrefix(a, "foo_") && len(a) <= 7 
} 

func main() { 
    a := []string{"test", "some_other_test", "foo_etc"} 
    result := Choose(a, isNoFoo7) 
    fmt.Println(result) // [test] 
} 

興味深いことに:

私はそれはのように素敵なANと、移動中にこの種のものを実装することでしたいかに難しいかを見てみたかったです私が管理できるAPI。それは難しくありませんでした。 数年前にそれを書いたので、一度使ってみる機会はありませんでした。代わりに、私は "for"ループを使うだけです。 これを使用しないでください。

だから、ロブによると、ほとんどの慣用的な方法は、のようになります。このスタイルは、非常に類似し、そうでない場合は同じであるアプローチに任意のC-家族の言語がかかる

func main() { 
    a := []string{"test", "some_other_test", "foo_etc"} 
    nofoos := []string{} 
    for i := range a { 
     if(!strings.HasPrefix(a[i], "foo_") && len(a[i]) <= 7) { 
      nofoos = append(nofoos, a[i]) 
     } 
    } 
    fmt.Println(nofoos) // [test] 
} 

関連する問題