文字列から数値だけを取り出す

タグの編集
投稿者 もも  () 投稿日時 2011/2/4 18:14:30
初めまして。
文字列から数値を取り出す関数でValがありますが、文字列の最初が数値でないと0が返ってきて用途としては使えません。
他に文字列の中から数値だけを抽出する関数はありますでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/2/4 19:51:12
仕様をもう少し細かく決めておいてください。

たとえば "=SUM(A10:B23)" という文字列の場合、何が返ってくれば良いのでしょうか。
「10」でしょうか。「1023」でしょうか。それとも「10」と「23」でしょうか。

"A-1=B+2" の場合は、「12」なのか、「-1」なのか、あるいは「-1」と「2」なのかとか、
数値が一切入っていなかった場合はどうするのか、とか。

Dim S As String = "=SUM(A10:B23)"
'1023 が得られる 
Dim V As Double = Val(S.Where(Function(C) C Like "[.0-9]").ToArray())

投稿者 もも  () 投稿日時 2011/2/4 20:31:36
ありがとうございます。
単純に文字列中から数値を連結したものを返す変数を探していました。
しかし、いくら探しても見つからなかったので以下のように自作しました。

    Public Function GetNumber(ByVal Str As StringAs String

        Dim Search As String
        Dim ResultNumber As New StringBuilder

        For i As Integer = 1 To Str.Length

            Dim find As Boolean

            Search = Mid(Str, i, 1)
            find = Search Like "[0-9]"


            If find = True Then

                ResultNumber.Append(Search)

            End If

        Next i

        Return ResultNumber.ToString

    End Function



それにしても、魔界の仮面弁士さんのコードだとたった一行で実現できるスキルには感心しました。。
投稿者 (削除されました)  () 投稿日時 2011/2/4 23:00:37
(削除されました)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/2/5 09:24:11
> Public Function GetNumber(ByVal Str As String) As String
Str という変数名は避けた方が良いと思いますよ。

VB には『Str 関数』という物がありますので、たとえ動作上は問題が無くとも、
コードとして見たときに、どちらの意味であるのか分かりにくくなってしまいます。


> For i As Integer = 1 To Str.Length
>   Search = Mid(Str, i, 1)
String は Char の配列のように扱う事が出来ます。
そのため 1文字ずつ取り出す場合は、Mid 関数を使わずとも
 For i As Integer = 0 To Str.Length - 1
  Dim Search As Char = Str(i)
のようにして、String のインデクサを使って簡単に取り出すことができます。

# 上記の「Str(i)」は、Str関数の事ではなく、「Str.Chars(i)」の方の意味です。


さらに言えば、ループ処理を For から For Each に変更することで
 For Each Search As Char In Str
  If Search Like "[0-9]" Then
   ResultNumber.Append(Search)
  End If
 Next
のように短く書く事もできます。 
投稿者 よねKEN  (社会人) 投稿日時 2011/2/5 11:42:26
以下のようなやり方もあります。

VB2008以降、.NET Framework2.0以降で動作します。
Dim text As String = "=SUM(A10:B23)" 
Dim result As String = New String(Array.FindAll(text .ToCharArray(), Function(ch) ch Like "[0-9]"))
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/2/5 17:30:58
> VB2008以降、.NET Framework2.0以降で動作します。

便乗して、VB2005 対応案を幾つか。(result0 のみ、VB2008以降が対象となります)
'Dim result0 As String = Array.FindAll(text.ToCharArray(), Function(c) c Like "[0-9]") 
Dim result1 As String = Array.FindAll(text.ToCharArray(), AddressOf Char.IsDigit)
Dim result2 As String = Array.FindAll(text.ToCharArray(), AddressOf Char.IsNumber)
Dim result3 As String = Array.FindAll(text.ToCharArray(), AddressOf IsNumeric)


なお、変換元データが
Dim text As String = "X1弐Ⅲ4"
だった場合、これらは以下のような結果となります。

【Option Compare Text モードの場合】
result0 = "1Ⅲ4"
result1 = "14"
result2 = "1Ⅲ4"
result3 = "14"

【Option Compare Binary モードの場合】
result0 = "4"
result1 = "14"
result2 = "1Ⅲ4"
result3 = "14"


# 全角数字を数値化する場合、Val("123") は 0.0 ですが CDbl("123") は 123.0 です。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/2/5 17:46:12
> 便乗して、VB2005 対応案を幾つか。(result0 のみ、VB2008以降が対象となります)

失礼しました。result3 も VB2008 以降でないと動作しませんね。
投稿者 もも  () 投稿日時 2011/2/6 00:45:53
魔界の仮面弁士さん、よねKENさんありがとうございます。
色々とご指摘して頂けて本当に勉強になります。
VBを始めて1年ほどですが、知らない関数や記述ルールなどがあって、まだまだ勉強不足だと実感しました。
これからもよろしくお願いします。
投稿者 shu  (社会人) 投稿日時 2011/2/6 22:04:46
正規表現を使った場合です。

Imports System.Text.RegularExpressions

・・・・

Dim reg As New Regex("[^\d]")   '--- [^0-9]でもよい
Dim strSrc As String = "=SUM(A32:B48)"
Dim strDes As String = reg.Replace(strSrc, "")