仕事でどうしてもVBScriptで新規コードを書かねばならず、LINQに慣れ過ぎてしまった私には、もはやLINQの無い世界は考えられなかったのです。
Windows 2000 Server+IIS5。.NETも入っていません。
検索すると、こんな素敵なクラスを作ってくださってる方がいらっしゃいました。
素敵です。
しかし、いくら素敵なリストクラスがあっても、WhereやSelectが無いのでは、使いでがありません。
かといって、VBScriptには匿名関数などといった素敵なものはなく、引数に評価関数を渡す方法が無い以上、どうしようもありません・・・いや待て、我々にはEval関数があるではないですか!
そんなわけで、こんな風に書ける事を確認したので安心して今日は寝ます。
同じ地獄にいるみんなの心が多少なりとも癒されることを祈りつつ。
Dim list
Set list = New ArrayList
Call list.Add( (New Person)( "001", "Taro Yamada", 20 ) )
Call list.Add( (New Person)( "002", "Mike Davis", 20 ) )
Call list.Add( (New Person)( "003", "Tom Wilson", 21 ) )
Dim i
For Each i In list.Where( "item.Age = 20").Items
MsgBox i.Name 'Taro Yamada、Mike Davis を順に表示
Next
For Each i In list.Where( "item.Age = 20").Map( "item.ID & "":"" & item.Name" ).Items
MsgBox i '001:Taro Yamada、002:Mike Davis を順に表示
Next
全てのソースコードはこちら。
ArrayList.vbs
Call Main()
Sub Main
Dim list
Set list = New ArrayList
Call list.Add( (New Person)( "001", "Taro Yamada", 20 ) )
Call list.Add( (New Person)( "002", "Mike Davis", 20 ) )
Call list.Add( (New Person)( "003", "Tom Wilson", 21 ) )
Dim i
For Each i In list.Where( "item.Age = 20").Items
MsgBox i.Name
Next
For Each i In list.Where( "item.Age = 20").Map( "item.ID & "":"" & item.Name" ).Items
MsgBox i
Next
End Sub
Class ArrayList
Private pItems
Private pKeyMax
Private Sub Class_Initialize
Set pItems = Server.CreateObject("Scripting.Dictionary")
pKeyMax = 0
End Sub
Private Sub Class_Terminate
Set pItems = Nothing
End Sub
Public Property Get Count
Count = pItems.Count
End Property
Public Property Get Items
Items = pItems.Items
End Property
Public Sub Add( item )
pItems.Add pKeyMax, item
pKeyMax = pKeyMax + 1
End Sub
Public Function Where( expr )
Dim list
Set list = New ArrayList
Dim item
For Each item In pItems.Items
If Eval( expr ) Then
list.Add item
End If
Next
Set Where = list
End Function
Public Function Map( expr )
Dim list
Set list = New ArrayList
Dim item
For Each item In pItems.Items
list.Add Eval( expr )
Next
Set Map = list
End Function
End Class
Class Person
Public ID
Public Name
Public Age
Private Sub Class_Initialize
ID = ""
Name = ""
Age = 0
End Sub
Public Default Property Get Init( pid, pname, page )
ID = pid
Name = pname
Age = page
Set Init = Me
End Property
End Class
追記!
パワーアップして、C#のラムダ式っぽく、要素を渡す変数名も書けるようにしてみました。
けど、要素名はitem固定でいいと思うので、こっちは使わないかな?
ArrayList
Call Main()
Sub Main
Dim list
Set list = New ArrayList
Call list.Add( (New Person)( "001", "Taro Yamada", 20 ) )
Call list.Add( (New Person)( "002", "Mike Davis", 20 ) )
Call list.Add( (New Person)( "003", "Tom Wilson", 21 ) )
Dim item
For Each item In list.Where( "p => p.Age = 20").Items
MsgBox item.Name
Next
For Each item In list.Where( "p => p.Age = 20").Map( "p => p.ID & "":"" & p.Name" ).Items
MsgBox item
Next
End Sub
Class ArrayList
Private pItems
Private pKeyMax
Private Sub Class_Initialize
Set pItems = Server.CreateObject("Scripting.Dictionary")
pKeyMax = 0
End Sub
Private Sub Class_Terminate
Set pItems = Nothing
End Sub
Public Property Get Count
Count = pItems.Count
End Property
Public Property Get Items
Items = pItems.Items
End Property
Public Sub Add( item )
pItems.Add pKeyMax, item
pKeyMax = pKeyMax + 1
End Sub
Public Function Where( expr )
Dim paramName, exprRight
paramName = Split( expr, "=>")(0)
exprRight = Split( expr, "=>")(1)
Dim list
Set list = New ArrayList
Dim itemInner
For Each itemInner In pItems.Items
Execute( "Dim " & paramName )
Execute( "Set " & paramName & " = itemInner" )
If Eval( exprRight ) Then
list.Add itemInner
End If
Next
Set Where = list
End Function
Public Function Map( expr )
Dim paramName, exprRight
paramName = Split( expr, "=>")(0)
exprRight = Split( expr, "=>")(1)
Dim list
Set list = New ArrayList
Dim itemInner
For Each itemInner In pItems.Items
Execute( "Dim " & paramName )
Execute( "Set " & paramName & " = itemInner" )
list.Add Eval( exprRight )
Next
Set Map = list
End Function
End Class
Class Person
Public ID
Public Name
Public Age
Private Sub Class_Initialize
ID = ""
Name = ""
Age = 0
End Sub
Public Default Property Get Constructor( pid, pname, page )
ID = pid
Name = pname
Age = page
Set Init = Me
End Property
End Class