1

すべての行がリストのインデックス内にある字幕ファイル(.srt)からリストを作成しました。ここで、いくつかの行、特に「xx:xx:xx、xxx-> xx:xx:xx、xxx」の形式の時間間隔で始まる行を消去したいと思います。私はいくつかの調査を行い(わかりました、複雑なトピックに関する非常に表面的な調査、追加するかもしれません)、次のサブを作成しようとしました:

Private Shared Sub listCleaning(ByRef sList As List(Of String))
    For Each line As String In sList
        Dim pattern As String = "\b\d\d:\d\d:\d\d:\d\d,\d\d\d --> \b\d\d:\d\d:\d\d:\d\d,\d\d\d"
        Dim reg As New Regex(pattern)

        If line = "" Or Integer.TryParse(line, Nothing) Or reg.IsMatch(pattern) Then
            sList.Remove(line)
        End If
    Next
End Sub

今私は2つの問題を抱えています:

  1. 正規表現が正しく解析されていません。
  2. Ifブロックに有効な条件があり、行が削除されると、リストが変更されたため、次を押すときにInvalidOperationExceptionが発生します。

誰かが正しい正規表現を書いて、不要な行を削除してリストを反復処理する方法を教えてもらえますか?

事前にt​​nx。

編集:

わかりました。Timは問題のほとんどを解決しましたが、パターン「xx:xx:xx、xxx-> xx:xx:xx、xxx」に適合する正規表現が必要です。気にかけてくれる人はいますか?

前もって感謝します!

4

2 に答える 2

1

これらは、元のコードに対する私の変更です。

まず、for eachループは使用しませんが、より伝統的なforループです
。次に、ループを逆にして、削除をリストの最後に移動します
。3番目に、正規表現パターンはループの外側にある必要があります。

Private Shared Sub listCleaning(ByRef sList As List(Of String)) 
    Dim pattern As String = "\d{2}:\d{2}:\d{2},\d{3}\s+-->\s+\d{2}:\d{2}:\d{2},\d{3}" 
    Dim reg As New Regex(pattern) 
    Dim x as Integer
    For x = sList.Count - 1 to 0 step -1
        Dim line as string = sList(x)
                Console.WriteLine(line)
        If line = "" Or Integer.TryParse(line, Nothing) Or reg.IsMatch(line) Then 
               sList.Remove(line) 
        End If 
    Next 
End Sub 

これは私のテストデータです:

Sub Main
    Dim sList as List(Of String) = new List(Of string)
    sList.Add("01:01:01,003 --> 02:02:02,003")
    sList.Add("sdsdfsdfsd03 --> 02:02:02,003")
    sList.Add("03:01:01,003 --> 03:02:02,003")
    sList.Add("04:01:01,003 --> 04:02:02,003")
    sList.Add("05:01:01,003 --> 05:02:02,003")
    sList.Add("06:01:01,003 --> 06:02:02,003")
    sList.Add("07:01:01,003 --> 07:02:02,003")
    sList.Add("08:01:01,003 --> 08:02:02,003")
    sList.Add("09:01:01,003 --> 02:02:02 003")    

    console.WriteLine("Call listCleaning with " + sList.Count.ToString +  " elements")

    listCleaning(sList)

    console.WriteLine("Returned with " + sList.Count.ToString +  " elements")
    for each line as String in sList
        Console.WriteLine(line)
    next
End Sub

この出力を取得するには

Call listCleaning with 9 elements
09:01:01,003 --> 02:02:02 003
08:01:01,003 --> 02:02:02,003
07:01:01,003 --> 02:02:02,003
06:AA:01,003   --> 02:02:02,003
05:01:01,003 -->    02:02:02,003
04:01:01,003 --> 02:02:02,003
03:01:01,003 --> 02:02:02,003
sdsdfsdfsd03 --> 02:02:02,003
01:01:01,003 --> 02:02:02,003
Returned with 3 elements
sdsdfsdfsd03 --> 02:02:02,003
06:AA:01,003   --> 02:02:02,003
09:01:01,003 --> 02:02:02 003
于 2012-07-14T20:50:18.153 に答える
0

ポイント2への回答:

反復中にコレクションを変更することはできません。だからあなたは

  1. 削除するアイテムを別のコレクションに保存する必要がある、または
  2. 逆に繰り返す(@Odedに感謝)または
  3. 使用List.RemoveAll(下部を参照)または
  4. Linqを使用する:

    var dontRemove = From line In sList
        Where line <> "" AndAlso Not Integer.TryParse(line, Nothing) AndAlso Not reg.IsMatch(pattern)
    

これで、これらの行をリストから安全に削除するか、新しいリストを作成することができます。

sList = dontRemove.ToList()

List(Of T)最良のオプションを使用している場合はList.RemoveAll、削除する必要のあるアイテムを使用して述語を渡すことです。

Dim regex = New Regex("\d{2}:\d{2}:\d{2},\d{3}\s+-->\s+\d{2}:\d{2}:\d{2},\d{3}", RegexOptions.Compiled)
sList.RemoveAll(Function(line) line.Length = 0 _
                    OrElse Integer.TryParse(line, Nothing) _
                    OrElse Not regex.IsMatch(line))

リストを逆に繰り返すための最良の方法は何ですか

For index As Int32 = sLines.Count - 1 To 0 Step -1
    Dim line = sLines(index)
Next`
于 2012-07-14T20:40:25.003 に答える