开发者

How to convert a string of key/value pairs to HashTable or Dictionary or?

In VB.NET, how can I convert the following string into some kind of key/value type such as a Hashtable, Dictionary, etc?

"Name=Fred;Birthday=19-June-1906;ID=12345"

I want to开发者_如何学运维 extract Birthday or ID without having to split the string into an array.

EDIT: I'd prefer not to split the string into an array in case the format of the string changes later. I don't have control over the string. What if someone switches the order around or adds another element?


I’m currently unable to test this, lacking a VB compiler, but the following solution should also work, and it has the advantage of not requiring an explicit loop. It uses the Linq method ToDictionary and two nested Split operations:

Dim s = "Name=Fred;Birthday=19-June-1906;ID=12345"
Dim d = s.Split(";"c).Select(Function (kvp) kvp.Split("="c)) _
    .ToDictionary( _
        Function (kvp) kvp(0), _
        Function (kvp) kvp(1))

First, we split on the outer delimiter (i.e. the semi-colon). From the resulting array, we select by splitting again, this time on =. The resulting array of arrays is converted to a dictionary by specifying that the first item is to become the key and the second is to become the value (the identifier kvp stands for “key-value pair”).

Since I can’t check the exact VB syntax and the above may contain subtle errors, here is the equivalent C# code (tested for correctness):

var s = "Name=Fred;Birthday=19-June-1906;ID=12345";
var d = s.Split(';').Select(kvp => kvp.Split('='))
    .ToDictionary(kvp => kvp[0], kvp => kvp[1]);


Not sure why you don't want to split it. If you're sure there won't be any extra = or ; then you could just do:

Dim s As String = "Name=Fred;Birthday=19-June-1906;ID=12345"
Dim d As New Dictionary(Of String, String)
For Each temp As String In s.Split(";"c)
    Dim index As Int32 = temp.IndexOf("="c)
    d.Add(temp.Substring(0, index), temp.Substring(index + 1))
Next

Which might not be beautiful, but is very easy to understand.


input.Split(";"c) returns an array of key/value:

{ "Name=Fred", "Birthday=19-June-1906" , "ID=12345" }

so pair.Split("="c) returns { "Name", "Fred" } etc


If you want an alternative to doing a String.Split; there is always Regular Expressions as an alternative:

Dim map As Dictionary(Of String, String) = New Dictionary(Of String, String)
Dim match As Match = Regex.Match("Name=Fred;Birthday=19-June-1906;ID=12345", "(?<Name>[^=]*)=(?<Value>[^;]*);?")

While (match.Success)
  map.Add(match.Groups("Name").Value, match.Groups("Value").Value)
  match = match.NextMatch()
End While

The regular expression itself could be beefed up to better handle whitespace between key/value's and pair's but you hopefully get the idea. This should only pass through the string once to build up a string dictionary of keys and values.


 Dim persSeparator as string=";"
 Dim keyValSeparator as string="=";
 Dim allPersons As New Dictionary(Of String, Person)
 Dim str As String = "Name=Fred;Birthday=19-June-1906;ID=12345"
 Dim parts As New List(Of String)(str.Split(persSeparator.ToCharArray)) 'why dont want you to split this string??
 Dim person As New Person
 For Each part As String In parts
     Dim keyValue() As String = part.Split(keyValSeparator.toCharArray())
     Select Case keyValue(0).ToUpper
         Case "ID"
             person.ID = keyValue(1)
         Case "NAME"
             person.Name = keyValue(1)
         Case "BIRTHDAY"
             person.BirthDay= keyValue(1)
    End Select
Next
If Not allPersons.ContainsKey(person.ID) Then
    allPersons.Add(person.ID, person)
End If


Public Class Person
    Private _name As String
    Private _birthday As String
    Private _id As String = String.Empty

    Public Sub New()
    End Sub

    Public Sub New(ByVal id As String)
        Me._id = id
    End Sub

    Public Sub New(ByVal id As String, ByVal name As String)
        Me._id = id
        Me._name = name
    End Sub

    Public Sub New(ByVal id As String, ByVal name As String, ByVal birthday As String)
         Me._id = id
         Me._name = name
         Me._birthday = birthday
    End Sub

    Public Property ID() As String
        Get
            Return Me._id
        End Get
        Set(ByVal value As String)
            Me._id = value
        End Set
    End Property

    Public Property Name() As String
        Get
            Return Me._name
        End Get
        Set(ByVal value As String)
            Me._name = value
        End Set
    End Property

    Public Property BirthDay() As String
        Get
            Return Me._birthday
        End Get
        Set(ByVal value As String)
            Me._birthday = value
        End Set
    End Property

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        If TypeOf obj Is Person AndAlso Not obj Is Nothing Then
            Return String.Compare(Me._id, DirectCast(obj, Person).ID) = 0
            Else : Return False
        End If
    End Function
 End Class


If you were just wanting to extract the birthday and ID from the string and place as a value pair in some sort of dictionary, for simplicity I would use regular expressions and then a generic dictionary (of string, valuepair structure). Something like this:

Imports System.Text.RegularExpressions
Imports System.Collections.Generic

Sub Main()

    Dim Person As New Dictionary(Of String, ValuePair)

    Dim s As String = "Name=Fred;Birthday=19-June-1906;ID=12"
    Dim r As Regex = New Regex("Name=(.*);Birthday=(.*);ID=(.*$)")
    Dim m As Match = r.Match(s)

    Person.Add(CStr(m.Groups(1).Value), _
        New ValuePair(CDate(m.Groups(2).Value), CInt(m.Groups(3).Value)))

    Console.WriteLine(Person("Fred").Birthday.ToString)
    Console.WriteLine(Person("Fred").ID.ToString)

    Console.Read()

End Sub

Friend Structure ValuePair

    Private _birthday As Date
    Private _ID As Int32

    Public ReadOnly Property ID() As Int32
        Get
            Return _ID
        End Get
    End Property

    Public ReadOnly Property Birthday() As Date
        Get
            Return _birthday
        End Get
    End Property

    Sub New(ByVal Birthday As Date, ByVal ID As Int32)
        _birthday = Birthday
        _ID = ID
    End Sub

End Structure
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜