汎用機メモっとくか

しごと用の(学習メモ&お気に入り保存)。

VBScript 複数キーでソート(クイックソート)

2014年03月20日 01時05分47秒 | WSH

VBScript 複数キーでソート(クイックソート)

VBScriptクイックソートのソースCOPY元
  「VBScript でソートする (unibon)」様
http://www.geocities.co.jp/SiliconValley/4334/unibon/asp/vbscriptsort.html  

更新しようとしたらぶっ壊れました。
再編集しようとすると HTMLかgooブログの仕様みたいで、"<" ">" がうまく入りません。
「<」multi を 「<」singleに置き換えてください。
「>」multi を 「>」singleに置き換えてください。

&lt; と &gt; でエスケープしてみたが、
&gt;(>)は、うまくいくが、&lt;(<)の
とある部分から、全部イタリックに変わる現象発生のため。


'<クイックsort.vbs>
'「<」multi を 「<」singleに置き換えてください。
'「>」multi を 「>」singleに置き換えてください。

Option Explicit
MsgBox "処理開始"
    Dim key_num
    Dim key_idx(9)
    Dim key_dir(9)
    Dim key_typ(9)
   
    key_num = 3  'keyの個数
    ReDim sortKEY(key_num)
   
    'key001
    key_idx(0) = 0 'キーのカラム番号
    key_dir(0) = 0 '0:昇順 1:降順
    key_typ(0) = 0 '0:文字 1:数字
   
    'key002
    key_idx(1) = 1 'キーのカラム番号
    key_dir(1) = 1 '0:昇順 1:降順
    key_typ(1) = 0 '0:文字 1:数字
   
    'key003
    key_idx(2) = 4 'キーのカラム番号
    key_dir(2) = 1 '0:昇順 1:降順
    key_typ(2) = 1 '0:文字 1:数字
   
    Dim strPathIn
    Dim strPathOut
   
    Dim oFS
    Dim oFR
    Dim oFW
   
    Dim oDic1
    Set oDic1 = CreateObject("Scripting.Dictionary")
    Dim oDic2
    Set oDic2 = CreateObject("Scripting.Dictionary")
   
    Dim myDATA
    Dim myCSV
    Dim myItems
   
    Dim i
    Dim j
    Dim iMax
    Dim iMin
    Dim chgWK
   
    const ForReading = 1,ForWriting = 2,ForAppending = 8
   
    strPathIn  = "TEST_IN65536.dat"
    'strPathIn  = "TEST_IN6000_2.dat"
    strPathOut = "test_IN65536_クイックout.txt"
   
    Set oFS = CreateObject("Scripting.FileSystemObject")
    If oFS.fileExists(strPathIn) Then
        Set oFR = oFS.OpenTextFile(strPathIn,  ForReading)
        Set oFW = oFS.OpenTextFile(strPathOut, ForWriting, True)

        i = 0
        Do While Not oFR.AtEndOfStream
           myDATA = oFR.ReadLine
           oDic1.Add  i,  myDATA
           myCSV = Split(myDATA,",")

           For j = 0 To key_num - 1
               sortKEY(j) = myCSV(key_idx(j))
           Next
           sortKEY(key_num) = i
           oDic2.ADD i, sortKEY
           i = i + 1
        Loop
        iMax = i - 1
        oFR.Close
        Set oFR = Nothing
       
        myItems = oDic2.Items
        MsgBox "キー作成完了。ソートします。"
       
        'クイックソート
        If 0 < UBound(myItems) Then
            Call sortQuickSub(myItems, 0, UBound(myItems))
        End If

        MsgBox "ソート完了。出力します。"
        For i = 0 To iMax
            oFW.WriteLine oDic1.Item(myItems(i)(key_num))
        Next
        oFW.Close
        Set oFW = Nothing
    Else
       Call MsgBox("ファイルが見つかりません!",48,"エラー")
    End If

    Set oFS = Nothing
    Set oDic1 = Nothing
    Set oDic2 = Nothing
    MsgBox "処理終了"

Sub sortQuickSub(ByRef a, ByVal p, ByVal q) ' クイックソート(内部ルーチン)
    Dim a001
    Dim b001
    Dim chgwk
    Dim i
    i = p
    Dim j
    j = q
    Dim x
    x = a(p)
    Do
        'Do While a(i) < x
        Do While func_compare(a(i), x)
            i = i + 1
        Loop
        'Do While x < a(j)
        Do While func_compare(x, a(j))       
            j = j - 1
        Loop

        If i >= j Then
            Exit Do
        End If

        'Call swap(a(i), a(j))
        chgwk = a(i)
        a(i)  = a(j)
        a(j)  = chgwk

        i = i + 1
        j = j - 1
    Loop

    If p < i - 1 Then
        Call sortQuickSub(a, p, i - 1)
    End If

    If j + 1 < q Then
        Call sortQuickSub(a, j + 1, q)
    End If
End Sub

Function func_compare(a01,b01)
    Dim k
    For k = 0 To key_num - 1
        If key_typ(k) = 1 Then
            If key_dir(k) = 1 Then
                If CDbl(a01(k)) > CDbl(b01(k)) Then
                    func_compare = True : Exit Function
                End If
                If CDbl(a01(k)) < CDbl(b01(k)) Then
                    func_compare = False  : Exit Function
                End If
            Else
                If CDbl(a01(k)) < CDbl(b01(k)) Then
                    func_compare = True : Exit Function
                End If
                If CDbl(a01(k)) > CDbl(b01(k)) Then
                    func_compare = False  : Exit Function
                End If
            End If
        Else
            If key_dir(k) = 1 Then
                If CStr(a01(k)) > CStr(b01(k)) Then
                    func_compare = True : Exit Function
                End If
                If CStr(a01(k)) < CStr(b01(k)) Then
                    func_compare = False  : Exit Function
                End If
            Else
                If CStr(a01(k)) < CStr(b01(k)) Then
                    func_compare = True : Exit Function
                End If
                If CStr(a01(k)) > CStr(b01(k)) Then
                    func_compare = False  : Exit Function
                End If
            End If
        End If
    Next
    If Clng(a01(key_num)) < Clng(b01(key_num)) Then
       func_compare = True
    Else
       func_compare = False
    End If
End Function

<csv_seed.vbs>
'「CSV種.vbs」
Option Explicit

Const ForReading  = 1
Const ForWriting  = 2
Const ForAppeding = 8

Dim strPathIn
Dim strPathOut
Dim oFS
Dim oFW

Dim i
Dim work(4)

Dim j
Dim signA(2)

strPathOut = "TEST_IN65536.dat"
Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFW = oFS.OpenTextFile(strPathOut,ForWriting,True)

Randomize
For i = 1 To 65536
    work(0) = Chr(Int(Rnd()*7 + 65)) & Chr(Int(Rnd()*7 + 65))
    work(1) = Chr(Int(90-Int(Rnd()*3)))
  
    For j = 0 To 2
        If  Int(Rnd()*2) = 1 Then
            signA(j) = "-"
        Else
            SignA(j) = ""
        End If
    Next

    work(2) = SignA(0)  & _
              (Int(Rnd()* 10000000000000))
    work(3) = SignA(1) & _
              (Int(Rnd()* 10000000000000))
    work(4) = SignA(2) & _
              (Int(Rnd()* 10000000000000))

    oFW.WriteLine Join(work,",")
Next

oFW.Close
Set oFW = Nothing
Set oFS = Nothing

Wscript.Echo "処理終了"

 

<check_result.vbs>
 Option Explicit

    Dim INFILE:INFILE = "test_IN65536_クイックout.txt"
    Dim OTFILE:OTFILE = "Check_result.txt"
   
    Dim oFS
    Dim oFR
    Dim oFW
   
    Const ForReading = 1
    Const ForWriting = 2
    Const ForAppending = 8

    Set oFS = CreateObject("Scripting.FileSystemObject")
    Set oFR = oFS.OpenTextFile(INFILE, ForReading)
    Set oFW = oFS.OpenTextFile(OTFILE, ForWriting, True)
   
    Dim myCSV
    Dim a001  
    Do While Not oFR.AtEndOfStream
        myCSV = Split(oFR.ReadLine,",")
        a001 = Mid(Space(16) & myCSV(4),Len(myCSV(4))+1,16)
        oFW.WriteLine(myCSV(0) & " "  & myCSV(1) &  a001)
    Loop
      
    oFW.Close
    oFR.Close

    Set oFW = Nothing
    Set oFR = Nothing
    Set oFS = Nothing
   
    MsgBox "処理終了"

<20180715追記>スタックオーバになるときなど用
テキストデータ複数キーの場合、こちらが使えるかも です。
自己記事 「便利 ADO でSORT」 テキストデータのソートです。
https://blog.goo.ne.jp/tkhs1732/e/37df39c1834c4c2bd4337956bf3675f4


VBScript 複数キーでソート(基本選択法)

2014年03月18日 01時59分10秒 | WSH

VBScript 複数キーでソート(基本選択法)

3keyで3000件くらいが無難。

<基本選択sort.vbs>
Option Explicit
MsgBox "処理開始"
    Dim key_num
    Dim key_idx(9)
    Dim key_dir(9)
    Dim key_typ(9)
   
    key_num = 3  'keyの個数
    ReDim sortKEY(key_num)
   
    'key001
    key_idx(0) = 0 'キーのカラム番号
    key_dir(0) = 0 '0:昇順 1:降順
    key_typ(0) = 0 '0:文字 1:数字
   
    'key002
    key_idx(1) = 1 'キーのカラム番号
    key_dir(1) = 1 '0:昇順 1:降順
    key_typ(1) = 0 '0:文字 1:数字
   
    'key003
    key_idx(2) = 4 'キーのカラム番号
    key_dir(2) = 1 '0:昇順 1:降順
    key_typ(2) = 1 '0:文字 1:数字
   
    Dim strPathIn
    Dim strPathOut
   
    Dim oFS
    Dim oFR
    Dim oFW
   
    Dim oDic1
    Set oDic1 = CreateObject("Scripting.Dictionary")
    Dim oDic2
    Set oDic2 = CreateObject("Scripting.Dictionary")
   
    Dim myDATA
    Dim myCSV
    Dim myItems
   
    Dim i
    Dim j
    Dim iMax
    Dim iMin
    Dim chgWK
   
    const ForReading = 1,ForWriting = 2,ForAppending = 8
   
    strPathIn  = "test_IN3000.dat"
    'strPathIn  = "TEST_IN6000_2.dat"
    strPathOut = "test_IN3000_基本選択out.txt"
   
    Set oFS = CreateObject("Scripting.FileSystemObject")
    If oFS.fileExists(strPathIn) Then
        Set oFR = oFS.OpenTextFile(strPathIn,  ForReading)
        Set oFW = oFS.OpenTextFile(strPathOut, ForWriting, True)

        i = 0
        Do While Not oFR.AtEndOfStream
           myDATA = oFR.ReadLine
           oDic1.Add  i,  myDATA
           myCSV = Split(myDATA,",")

           For j = 0 To key_num - 1
               sortKEY(j) = myCSV(key_idx(j))
           Next
           sortKEY(key_num) = i
           oDic2.ADD i, sortKEY
           i = i + 1
        Loop
        iMax = i - 1
        oFR.Close
        Set oFR = Nothing
       
        myItems = oDic2.Items
        MsgBox "キー作成完了。ソートします。"
       
        '基本選択法ソート
        For i =0 To iMax - 1
            iMin = i
            For j = i + 1 To iMax
                If func_compare(myItems(iMin),myItems(j)) Then
                    iMin = j
                End If
            Next
            chgWK = ""
            chgWK = myItems(i)
            myItems(i) = myItems(iMin)
            myItems(iMin) = chgWK
        Next
        MsgBox "ソート完了。出力します。"
        For i = 0 To iMax
            oFW.WriteLine oDic1.Item(myItems(i)(key_num))
        Next
        oFW.Close
        Set oFW = Nothing
    Else
       Call MsgBox("ファイルが見つかりません!",48,"エラー")
    End If

    Set oFS = Nothing
    Set oDic1 = Nothing
    Set oDic2 = Nothing
    MsgBox "処理終了"

Function func_compare(a01,b01)
    Dim k
    For k = 0 To key_num - 1
        If key_typ(k) = 1 Then
            If key_dir(k) = 1 Then
                If CDbl(a01(k)) > CDbl(b01(k)) Then
                    func_compare = False : Exit Function
                End If
                If CDbl(a01(k)) < CDbl(b01(k)) Then
                    func_compare = True  : Exit Function
                End If
            Else
                If CDbl(a01(k)) < CDbl(b01(k)) Then
                    func_compare = False : Exit Function
                End If
                If CDbl(a01(k)) > CDbl(b01(k)) Then
                    func_compare = True  : Exit Function
                End If
            End If
        Else
            If key_dir(k) = 1 Then
                If CStr(a01(k)) > CStr(b01(k)) Then
                    func_compare = False : Exit Function
                End If
                If CStr(a01(k)) < CStr(b01(k)) Then
                    func_compare = True  : Exit Function
                End If
            Else
                If CStr(a01(k)) < CStr(b01(k)) Then
                    func_compare = False : Exit Function
                End If
                If CStr(a01(k)) > CStr(b01(k)) Then
                    func_compare = True  : Exit Function
                End If
            End If
        End If
    Next
    If Clng(a01(key_num)) < Clng(b01(key_num)) Then
       func_compare = False
    Else
       func_compare = True
    End If
End Function

 

<CSV_seed.vbs>
'「CSV種.vbs」
Option Explicit

Const ForReading  = 1
Const ForWriting  = 2
Const ForAppeding = 8

Dim strPathIn
Dim strPathOut
Dim oFS
Dim oFW

Dim i
Dim work(4)

Dim j
Dim signA(2)

strPathOut = "TEST_IN3000.dat"
Set oFS = CreateObject("Scripting.FileSystemObject")
Set oFW = oFS.OpenTextFile(strPathOut,ForWriting,True)

Randomize
For i = 1 To 3000
    work(0) = Chr(Int(Rnd()*5 + 65)) & Chr(Int(Rnd()*5 + 65))
    work(1) = Chr(Int(90-Int(Rnd()*3)))
  
    For j = 0 To 2
        If  Int(Rnd()*2) = 1 Then
            signA(j) = "-"
        Else
            SignA(j) = ""
        End If
    Next

    work(2) = SignA(0)  & _
              (Int(Rnd()* 10000000000000))
    work(3) = SignA(1) & _
              (Int(Rnd()* 10000000000000))
    work(4) = SignA(2) & _
              (Int(Rnd()* 10000000000000))

    oFW.WriteLine Join(work,",")
Next

oFW.Close
Set oFW = Nothing
Set oFS = Nothing

Wscript.Echo "処理終了"

 

<check_result.vbs>
 Option Explicit
    '結果確認.vbs
    Dim INFILE:INFILE = "test_IN3000_基本選択out.txt"
    Dim OTFILE:OTFILE = "Check_result.txt"
   
    Dim oFS
    Dim oFR
    Dim oFW
   
    Const ForReading = 1
    Const ForWriting = 2
    Const ForAppending = 8

    Set oFS = CreateObject("Scripting.FileSystemObject")
    Set oFR = oFS.OpenTextFile(INFILE, ForReading)
    Set oFW = oFS.OpenTextFile(OTFILE, ForWriting, True)
   
    Dim myCSV
    Dim a001  
    Do While Not oFR.AtEndOfStream
        myCSV = Split(oFR.ReadLine,",")
        a001 = Mid(Space(16) & myCSV(4),Len(myCSV(4))+1,16)
        oFW.WriteLine(myCSV(0) & " "  & myCSV(1) &  a001)
    Loop
      
    oFW.Close
    oFR.Close

    Set oFW = Nothing
    Set oFR = Nothing
    Set oFS = Nothing
   
    MsgBox "処理終了"