こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

重複した文字列をカウントして取り出したい

初めて質問させていただきます。
VB初心者です。

ソートされた文字列の書き込まれたファイルを読み、

(文字列は、
”000”
”001”
”001”
”001”
”002”
”002”
”003”
といったように書き込まれています。)

そこから、3つ連続して並んでいる文字列を探し出して、
その文字列と、3つ連続していた文字列がいくつあったのか表示するプログラムを作りたいのですが、

どうにも処理速度が遅く、さらに行数が1万を超えると、応答なしになってしまいます。

どなたか、上手い処理の方法があれば、ぜひともご教授の程をお願いします。

Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
OpenFileDialog1.FileName = ""
OpenFileDialog1.InitialDirectory = "c:\"
If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
TextBox1.Text = My.Computer.FileSystem.ReadAllText _
(OpenFileDialog1.FileName, System.Text.Encoding.Default)
End If
End Sub

Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

Dim x As Integer
Dim xyz As Integer

'行数を調べる。
Dim i As Integer = TextBox1.Lines.Length
TextBox2.Text = (i - 1 & "行")
MessageBox.Show("一時停止")
For ix = 0 To i - 2
'1行目と2行目を比較
If TextBox1.Lines(x) = TextBox1.Lines(x + 1) Then
'2行目と3行目を比較
If TextBox1.Lines(x + 1) = TextBox1.Lines(x + 2) Then
'3つある番号を記入。
TextBox2.Text = TextBox2.Text + vbCrLf + TextBox1.Lines(x + 2)
'3回重複したことをカウント。
'MessageBox.Show("3発見")
xyz = xyz + 1
Else

End If

Else
End If
'調べる行を+1
x = x + 1
Next

TextBox2.Text = TextBox2.Text + vbCrLf + ("3つ以上は、" & xyz & "個")




End Sub

Private Sub OpenFileDialog1_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk

End Sub

Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged

End Sub
End Class

投稿日時 - 2009-04-24 22:45:48

QNo.4906272

困ってます

質問者が選んだベストアンサー

文字列の連結を
TextBox2.Text = TextBox2.Text + vbCrlf + TextBox1.Lines(x + 2)
といった具合に直接コントロールプロパティで行っているので
速度の低下を招いているのでしょう

ループの外で
Dim sb as New System.Text.StringBuilder
と宣言しておいて条件に合致した場合

sb.AppendLine( TextBox1.Lines( n ) )
xyz += 1

としてメモリー上で文字の連結をします

ループが終了したら
sb.AppendLine( String.Format( "3つ以上は、{0}個", sb.Length ) )
TextBox2.Text = sb.ToString()
といった具合にして見ましょう

重複チェック中の『応答無し』の対処としてはループ中の適当なタイミングでApplication.DoEventsを実行してみましょう

ループの中で
if x mod 100 = 0 then
  Application.DoEvents()
end if
といった具合に 100回ごとに実行するとか

また条件チェックを
if TextBox1.Lines(x) = TextBox1.Lines(x+1) AndAlso _
  TextBox1.Lines(x) = TextBox1.Lines(x+2) then
といった具合に 1つのif文で判定するとか

2つの条件を Andで連結すると毎回両方の条件をチェックします
AndAlsoで連結すると 前者『TextBox1.Lines(x) = TextBox1.Lines(x+1)』が不成立なら後者の条件はチェックしません

進行状況を可視化するために ProgressBarなどを使ったり
Labelなどに現在のチェックライン番号(または残数)を表示してみましょう

投稿日時 - 2009-04-24 23:55:18

補足

無事に解決しました。ありがとうございました。

投稿日時 - 2009-04-26 04:16:41

お礼

ありがとうございます。さっそく試してみます。

投稿日時 - 2009-04-25 00:50:35

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

textboxの.Linesで調べているのが原因だと思います。
文字列配列に取り込んで計算すれば、速くなると思います。
それと質問のプログラムでは3個以上を調べているはずなのに、4個以上に対処していないように見えます。
それと、1データのチェックに3データを調べるのは効率が悪いと思います。
と言う訳で以下のようなのはどうでしょうか?
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim xyz As Integer
'配列に取得
Dim d() As String = Split(TextBox1.Text, vbCrLf)
'配列の最大引数取得
Dim ub As Integer = UBound(d)
'元文字列の最後が改行の時にできる余計なデータ分を減らす
If d(ub) = "" Then ub = ub - 1
'行数を調べる。
Dim lines As Integer = ub + 1
TextBox2.Text = (lines & "行")
MessageBox.Show("一時停止")
'最初のデータは1個目
Dim n As Integer = 1
'2番目のデータから最後まで調べる
For i = 1 To ub
If d(i) = d(i - 1) Then
'前のデータと同じならn+1個目
n = n + 1
Else
'違うなら1個目
n = 1
End If
If n = 3 Then
'3つ目なら番号を記入。
TextBox2.Text = TextBox2.Text + vbCrLf + d(i)
xyz = xyz + 1
End If
Next
TextBox2.Text = TextBox2.Text + vbCrLf + ("3つ以上は、" & xyz & "個")
End Sub

p.s.
どうしてもlines()で取得する場合は、文字列に取り込んでTextBox1.Lines(x)でアクセスする回数を減らす方がいいと思います。

投稿日時 - 2009-04-25 20:55:13

お礼

ありがとうございます。
こちらの方法も、ぜひ試させていただきます。

投稿日時 - 2009-04-26 04:18:20

あなたにオススメの質問