LoginSignup
0
1

More than 5 years have passed since last update.

VBA 一般的な配列内の数字の並べ替えをするユーザー定義関数と謎

Last updated at Posted at 2018-04-09

乱数を発生させて、配列にいれて配列を並び替えて配列に入れます。

今回はtipsfoundのSubプロシージャを関数にしてみました。
配列が代入され、配列で返る。
この時にソートする方法はいくつかあるので TipFoundのサイトを見てください。今回は2つ関数化しました。

アルゴリズムの流れ

arに乱数を代入していきます。
この時にaarに同じものを代入します。
Brに関数でソートして配列で返します。
すると

予想:arは元のバラバラのまま、aarは元のバラバラのまま brはソート済み

ところが実際は

結果 aarのみバラバラ ar、brは配列がソートされてしまう

という結果になりました。

ByrefでもByvalでもソートされます。

さらに言うと、

arを別の配列に入れてもarはソートされる

みたいです。

正直tipsfoundのようにSubで受けても変わらないのかも。

という結果になりましたので、みなさんtipfoundを見てください。

ソートの使い道は3月から4月と1月

たとえば次のような定番の文章があります。

みなさま2018年4月になりました。2017年度も終わり、新しい年度が始まりました。文書ファイルを作成するときは注意しましょう。文書の保存期間の起算点は2019年度です。このため満5年後の期限の文書は2023年度末、3年後の期限の文書は2021年度末です。
この文書から正規表現で4桁の数字を抜きます。

かならず4桁の西暦のパターン文字列

西暦は1900年から2999年まであれば大体普通の文章は間に合います。
すると[0-9]{4}ではありません。
最初は1,2しかないからです。のこり3桁が0-9です。
すると必ず西暦が4桁しかない場合のパターン文字列は
[1-2]{1}[0-9]{3}
です。


buf = 'さっきに文章を代入してください(てぬき)
Dim M , Mc, SMc
With CreateObject("VbScript.RegExp")
.Pattern = "[1-9]{1}[0-9]{3}"
.Global=True
.MultiLine = True
Set Mc = .ExeCute(buf)
End With

とやるとMCは2017 2018 2019 2022 2023
が入ります

西暦を置換するときの絶対の法則

最大の年から次の年にずらす

というのが重要です。
これは2ケタでも変わりません。例外は 99-00のあたりくらいです。
最小の2017から2018にするとダブってしまいます。
このため配列をソートして、最大の西暦を求め、それからReplaceしなければなりません。
このため正規表現とともに、並べ替えが必要になるというわけです。

コード


'乱数を発生させ配列に代入します
Sub MakeRndArray()
Dim ar(99), br, aar(99)
Const low As Long = 1
Const high As Long = 99
Dim i As Long
For i = 0 To 99
ar(i) = Rnd()
aar(i) = ar(i) 'Copy And Keep Index Keep Array
Next
’どちらかの関数に代入します
br = InsertionSort(ar, LBound(ar), UBound(ar))
'br = QuickSort(ar, LBound(ar), UBound(ar))
Stop
End Sub

関数はここから


Function InsertionSort(ByRef data As Variant, ByVal low As Long, ByVal high As Long)
'https://www.tipsfound.com/vba/02020 Data Temp は型をLongに合わせると早くなる
Dim i As Variant
Dim k As Variant
Dim temp As Variant
For i = low + 1 To high
temp = data(i)
If data(i - 1) > temp Then
k = i

Do While k > low
If data(k - 1) <= temp Then
Exit Do
End If

data(k) = data(k - 1)
k = k - 1
Loop

data(k) = temp
End If
Next
InsertionSort = data
End Function

Function QuickSort(ByRef data As Variant, ByVal low As Long, ByVal high As Long)
'’https://www.tipsfound.com/vba/02020
Dim l As Long
Dim r As Long
l = low
r = high

Dim pivot As Variant
Dim temp As Variant
pivot = data((low + high) \ 2)



Do While (l <= r)
Do While (data(l) < pivot And l < high)
l = l + 1
Loop
Do While (pivot < data(r) And r > low)
r = r - 1
Loop

If (l <= r) Then
temp = data(l)
data(l) = data(r)
data(r) = temp
l = l + 1
r = r - 1
End If
Loop
If (low < r) Then
QuickSort = QuickSort(data, low, r)
End If
If (l < high) Then
QuickSort = QuickSort(data, l, high)
End If
QuickSort = data
End Function
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1