2012-06-29 10 views
5

Mam następujący ciąg, który chcę wyodrębnić części z:Dość String Manipulation

<FONT COLOR="GREEN">201 KAR 2:340.</FONT> 

W tym konkretnym przypadku, życzę, aby wyodrębnić numery 201,2 i 340, które będę później użyć do złączyć, tworząc kolejny ciąg:

http://www.lrc.state.ky.us/kar/201/002/340reg.htm

mam rozwiązanie, ale nie jest łatwo czytelny i wydaje się raczej niezgrabne. Obejmuje użycie funkcji średniej. Oto ona:

intTitle = CInt(Mid(strFontTag, 
        InStr(strFontTag, ">") + 1, 
        (InStr(strFontTag, "KAR") - InStr(strFontTag, ">")) 
          - 3)) 

Chciałbym wiedzieć, czy być może istnieje lepszy sposób podejścia do tego zadania. Zdaję sobie sprawę, że mógłbym stworzyć opisowe nazwy zmiennych, takie jak intPosOfEndOfOpeningFontTag, aby opisać, co robi pierwsza funkcja InStr, ale nadal wydaje mi się to niezrozumiałe.

Czy powinienem używać jakiejś funkcji podziału, regexu, czy bardziej eleganckiego sposobu, z którym jeszcze nie miałem do czynienia? Przez lata manipulowałem strunami i po prostu uważam, że musi być lepszy sposób. Dzięki.

+0

Muszę docenić kogoś, kto activly dba o czytelność ... niezbyt dobrze Nie wiem, jak. – gbtimmon

+5

Przepraszam, czy to VB.net, VBA czy VB6? – JimmyPena

+0

Wygląda bardziej jak * VBScript * z wszystkimi wykorzystywanymi w nim funkcjami wariantu. – Bob77

Odpowiedz

1

wyrażenia regularnego wzoru: <FONT[^>]*>.*?(\d+).*?(\d+).*?(\d+).*?<\/FONT>

1
<FONT[^>]*>[^\d]*(\d+)[^\d]*(\d+):(\d+)[^\d]*</FONT> 
+0

Niektórzy ludzie nie wiedzą, czym są wyrażenia regularne! –

1

Klasa

Imports System 
Imports System.IO 
Imports System.Text 
Imports System.Text.RegularExpressions 
Imports System.Xml 
Imports System.Xml.Linq 
Imports System.Linq 

Public Class clsTester 
    'methods 
    Public Sub New() 
    End Sub 

    Public Function GetTitleUsingRegEx(ByVal fpath$) As XElement 
     'use this function if your input string is not a well-formed 
     Dim result As New XElement(<result/>) 
     Try 
      Dim q = Regex.Matches(File.ReadAllText(fpath), Me.titPattern1, RegexOptions.None) 
      For Each mt As Match In q 
       Dim t As New XElement(<title/>) 
       t.Add(New XAttribute("name", mt.Groups("name").Value)) 
       t.Add(New XAttribute("num1", mt.Groups("id_1").Value)) 
       t.Add(New XAttribute("num2", mt.Groups("id_2").Value)) 
       t.Add(New XAttribute("num3", mt.Groups("id_3").Value)) 
       t.Add(mt.Value) 
       result.Add(t) 
      Next mt 
      Return result 
     Catch ex As Exception 
      result.Add(<error><%= ex.ToString %></error>) 
      Return result 
     End Try 
    End Function 

    Public Function GetTitleUsingXDocument(ByVal fpath$) As XElement 
     'use this function if your input string is well-formed 
     Dim result As New XElement(<result/>) 
     Try 
      Dim q = XElement.Load(fpath).Descendants().Where(Function(c) Regex.IsMatch(c.Name.LocalName, "(?is)^font$")).Where(Function(c) Regex.IsMatch(c.Value, Me.titPattern2, RegexOptions.None)) 
      For Each nd As XElement In q 
       Dim s = Regex.Match(nd.Value, Me.titPattern2, RegexOptions.None) 
       Dim t As New XElement(<title/>) 
       t.Add(New XAttribute("name", s.Groups("name").Value)) 
       t.Add(New XAttribute("num1", s.Groups("id_1").Value)) 
       t.Add(New XAttribute("num2", s.Groups("id_2").Value)) 
       t.Add(New XAttribute("num3", s.Groups("id_3").Value)) 
       t.Add(nd.Value) 
       result.Add(t) 

      Next nd 
      Return result 
     Catch ex As Exception 
      result.Add(<error><%= ex.ToString %></error>) 
      Return result 
     End Try 
    End Function 

    'fields 
    Private titPattern1$ = "(?is)(?<=<font[^<>]*>)(?<id_1>\d+)\s+(?<name>[a-z]+)\s+(?<id_2>\d+):(?<id_3>\d+)(?=\.?</font>)" 
    Private titPattern2$ = "(?is)^(?<id_1>\d+)\s+(?<name>[a-z]+)\s+(?<id_2>\d+):(?<id_3>\d+)\.?$" 
End Class 

Zastosowanie

Sub Main() 
     Dim y = New clsTester().GetTitleUsingRegEx("C:\test.htm") 
     If y.<error>.Count = 0 Then 
      Console.WriteLine(String.Format("Result from GetTitleUsingRegEx:{0}{1}", vbCrLf, y.ToString)) 
     Else 
      Console.WriteLine(y...<error>.First().Value) 
     End If 

     Console.WriteLine("") 
     Dim z = New clsTester().GetTitleUsingXDocument("C:\test.htm") 

     If z.<error>.Count = 0 Then 
      Console.WriteLine(String.Format("Result from GetTitleUsingXDocument:{0}{1}", vbCrLf, z.ToString)) 
     Else 
      Console.WriteLine(z...<error>.First().Value) 
     End If 
     Console.ReadLine() 
    End Sub 

Mam nadzieję, że to pomoże.

+0

Czy możesz wyjaśnić lub przynajmniej skomentować swój kod? Wydaje się, że robią znacznie więcej, niż było to wymagane, bez oczywistych "rezultatów jest XYZ". – Deanna

+0

@Deanna: czy wymieniłeś kod?Wysyłając odpowiedź w krótkim czasie, nie zawsze można komentować każdy fragment kodu ze szczegółami. Wymaga również, aby osoba pytająca wiedziała o tym. – Cylian

+0

Nie ma powodu, aby nie wyjaśniać 2 stron nieskomentowanego czarnego pola (i pozornie przesadnego) kodu do prostego ekstrakcji ciągów. Od tego czasu masz 4 miesiące, aby to skomentować :) – Deanna

0

Myślę, że @ Jean-François Corbett ma to prawo.

Ukryj ją w funkcji i nigdy nie patrzeć wstecz

Zmień swój kod do tego:

intTitle = GetCodesFromColorTag("<FONT COLOR="GREEN">201 KAR 2:340.</FONT>") 

Utwórz nową funkcję:

Public Function GetCodesFromColorTag(FontTag as String) as Integer 

    Return CInt(Mid(FontTag, InStr(FontTag, ">") + 1, 
       (InStr(FontTag, "KAR") - InStr(FontTag, ">")) 
       - 3)) 

End Function 
Powiązane problemy