質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

2回答

1521閲覧

文字列の中から数字を探すコードを書きたいです

退会済みユーザー

退会済みユーザー

総合スコア0

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

1クリップ

投稿2017/11/03 19:37

編集2017/11/03 20:17

#やりたいこと
例えば
"100時間"
という文字列があったとします。
この中から100という数字を探して、int型として抜き出したいです。

与えられる文字列の条件としては
・かならず 100時間 や 20分 のように数字+文字列の形となっています。
・必ず数字、文字列の順番です

#やったこと
**unicode.IsDigit()**にruneを渡せば判断できるようなので、それを使って関数を書いてみましたが...
https://play.golang.org/p/wrhXOE2aOD

go

1func main() { 2 factor := "100時間" 3 i := numCheck(factor) 4 fmt.Println(i) //output: 64469 5} 6 7func numCheck(factor string) int32 { 8 var num int32 9 for _, f := range factor { 10 if !unicode.IsDigit(f) { 11 num += f 12 } 13 } 14 return num 15}

これではint32の値しかわかりません。
このint32の値をintに変換するか、もしくはnumCheckの判別方法を根本的に変えないといけません。

もちろん、文字列の区切りを微調整しつつ**strconv.Atoi()**の返り値で判断するというようなこともできます。
以下例
https://play.golang.org/p/jR2zEwqr3I

go

1func numCheck(factor string) int { 2 var i = 0 3 for { 4 res, _ := strconv.Atoi(factor) 5 if res != 0 { 6 return res 7 } else { 8 factor = factor[:len(factor) - i] 9 } 10 i ++ 11 } 12} 13

正直どちらもくどいので、何かスマートな方法を探しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

文字列の先頭部分の数字の並びの取り出しを正規表現にまかせた例を書いてみました。

go

1package main 2 3import ( 4 "fmt" 5 "regexp" 6 "strconv" 7) 8 9func main() { 10 factor := "100時間" 11 i := ParseLeadingInt(factor) 12 fmt.Println(i) 13} 14 15var rexLeadingDigits = regexp.MustCompile(`\d+`) 16 17func ParseLeadingInt(s string) int { 18 rex := rexLeadingDigits.Copy() 19 value, _ := strconv.Atoi(rex.FindString(s)) 20 return value 21}

なお、複数モジュールから使うという想定で以下のようにしてます

  • 関数名先頭を大文字に
  • Regexp.Copyで複数goroutine対応

参照:https://golang.org/pkg/regexp/#Regexp.Copy

goには暗いのでおかしなところがあったらご容赦ください。

投稿2017/11/04 02:17

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/11/04 05:04 編集

回答ありがとうございます! なるほど、確かにregexpを使えば簡単にできますね 完全に失念していました 参考になります
KSwordOfHaste

2017/11/04 05:03

goの解説サイトなどみてて面白く感じたことがあります。「Regexpは他のスクリプト系言語のパフォーマンスと同等なので、性能的に問題」という言い方をしている点です。最初なにいってるかわかりませんでしたw; goはスピード重視の言語らしく、他の言語と同等性能ではgoとしてはイカン!ということなんでしょうかね。
退会済みユーザー

退会済みユーザー

2017/11/04 05:10

なるほどw すみません、もう一つ質問なんですが、`\d+`これはどういう意味ですか?
KSwordOfHaste

2017/11/04 05:22

\, d, +を含む3文字の文字列の表記の一つですが、"\d+"とも書けるようで、バッククォートで囲むと単にバックスラッシュなどの特殊文字をエスケープしなくてよくなるということのようです。他の言語にもよくあります。例えばC#でファイルパスを表現するときの var path="C:\a\b" と var path=@"C:\a\b" の違いみたいなものだと思います。
退会済みユーザー

退会済みユーザー

2017/11/04 05:30

バッククォートの使用用途等はわかるのですが、/d+の意味自体がわかりませんでした 調べたところ、正規表現の文法で/dが0~9の数値、+は「それ以降ずっと」という意味なので 「1文字以上の数値」という意味だとわかりました
KSwordOfHaste

2017/11/04 05:32 編集

・・・あ、そっちでしたか。正規表現の意味についてはおっしゃるとおりと思います。正確には+は「1回以上の任意の回数の繰り返し」です。
guest

0

ベストアンサー

これくらいであればパッケージを使わず書いた方がパフォーマンス出ます。

go

1package main 2 3import ( 4 "fmt" 5) 6 7func numCheck(s string) int { 8 n := 0 9 for _, r := range s { 10 if '0' <= r && r <= '9' { 11 n = n * 10 + int(r - '0') 12 } else { 13 break 14 } 15 } 16 return n 17} 18 19func main() { 20 factor := "100時間" 21 i := numCheck(factor) 22 fmt.Println(i) 23}

001 の場合も 1 になりますが。(もちろん strconv.Atoi でも同じです)

投稿2017/11/08 15:23

mattn

総合スコア5030

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問