文字列を比較演算子で比較するとどうなるか

文字列を比較演算子で比較する

文字列を比較演算子で比較した結果

何の気なしに、イミディエイトに次のように打ち込んで[Enter]してみた。

?"ち~んw" < "た~んw"

すると、

f:id:akashi_keirin:20180327084850j:plain

このように、Falseが返った。

んで、

?"ち~んw" < "つ~んw"

と入力して[Enter]すると、

f:id:akashi_keirin:20180327084909j:plain

このように、Trueが返った。

……ということは、文字列でもある程度ソートできるということだ。

もちろん、Excelのワークシートの機能を使えば楽勝なんだけれど、あくまでもプログラミングの練習、ということで。

配列を昇順バブルソートするFunction

ちょっと荒っぽいコードだけれど、配列を渡したら、配列の要素を昇順ソートした配列を返すFunctionのコードを書いてみた。

リスト1 標準モジュール
Public Function getSortedArrayByBubbleSort( _
                  ByRef targetArray As Variant) As Variant
  Dim buf As Variant
  Dim i As Long
  Dim j As Long
  For i = UBound(targetArray) To LBound(targetArray) Step -1    '……(1)'
    For j = LBound(targetArray) + 1 To i    '……(2)'
      If targetArray(j - 1) > targetArray(j) Then    '……(3)'
        buf = targetArray(j)    '……(4)'
        targetArray(j) = targetArray(j - 1)    '……(5)'
        targetArray(j - 1) = buf    '……(6)'
      End If
    Next
  Next
  getSortedArrayByBubbleSort = targetArray
End Function

(1)からの大ループと、(2)からの小ループの2重ループ。

大ループでは、引数で渡された添字の最大値から、最小値に向かって添字を減らしながらループする。

内側の小ループでは、2番目の要素から外側のループカウンタで示される要素までループする。

たとえば、引数で渡された配列targetArrayが5つの要素を持っているとすると、添字は

0,1,2,3,4

の5つ。

従って、大ループの2回目だと、小ループ内では、

targetArray(1)→targetArray(2)→targetArray(3)→……

の順で処理をすることになる。

(3)からの5行

If targetArray(j - 1) > targetArray(j) Then
  buf = targetArray(j)    '……(4)'
  targetArray(j) = targetArray(j - 1)    '……(5)'
  targetArray(j - 1) = buf    '……(6)'
End If

では、targetArray(j)の値を、隣の値targetArray(j - 1)と比較し、targetArray(j - 1)の方が大きかったら、

まず(4)の

buf = targetArray(j)

でtargetArray(j)の値を一時変数bufに格納し、

(5)の

targetArray(j) = targetArray(j - 1)

でtargetArray(j)にtargetArray(j - 1)の値を代入し、

(6)の

targetArray(j - 1) = buf

で先ほどbufに入れておいた元のtargetArray(j)の値をtargetArray(j - 1)に代入することにより、targetArray(j)とtargetArray(j - 1)のそれぞれの中身を交換している。

これを繰り返すことにより、

小ループが終わると、一番大きな値が最大の添字の要素になっている

ということだ。

全くイメージが湧かないと思うので、要素の動きを羅列してみよう。

もともと、targetArray(0)~targetArray(4)が、

4,2,5,3,1

の順に並んでいるとする。

大ループ1回目(i = 4)すなわち小ループ1周目

大ループの1回目は、小ループの1周目。すなわち、j = 0 + 1 から j = 4 までである。

j = 1

2,4,5,3,1

j = 2

2,4,5,3,1

j = 3

2,4,3,5,1

j = 4

2,4,3,1,5

大ループ2回目(i = 3)すなわち小ループ2周目

大ループの2回目は、小ループの2周目。すなわち、j = 0 + 1 から j = 3 までである。

j = 1

2,3,4,1,5

j = 2

2,3,4,1,5

j = 3

2,3,1,4,5

大ループ3回目(i = 2)すなわち小ループ3周目

大ループの3回目は、小ループの3周目。すなわち、j = 0 + 1 から j = 2 までである。

j = 1

2,3,1,4,5

j = 2

2,1,3,4,5

大ループ4回目(i = 1)すなわち小ループ4周目

大ループの4回目は、小ループの4周目。すなわち、j = 0 + 1 から j = 1 までである。

j = 1

1,2,3,4,5

1周目の大ループで、必ず1番大きな数が右端に追いやられ、2周目の大ループで2番目に大きな数が右端から2番目に追いやられ……を繰り返すことによって、左から昇順にソートしたことになるのが分かる。

実験

次のコードで、リスト1のFunctionを使ってみる。

スト2 標準モジュール
Public Sub testSortElementsByBubbleSort()
  Dim ar As Variant
  Dim el As Variant
  Dim i As Integer
  ar = getSortedArrayByBubbleSort( _
         Array("ち~んw", "て~んw", "た~んw", "つ~んw"))
  For Each el In ar
    Debug.Print el
  Next
End Sub

見ての通り、「ち~んw」、「て~んw」、「た~んw」、「つ~んw」の4要素からなる配列をgetSortedArrayByBubbleSortに渡して、返り値の要素を順に取り出して出力するだけのコード。

実行結果

f:id:akashi_keirin:20180327084918j:plain

無事、思っていた通りの出力が得られた。

おわりに

ワークシートの機能を使えば楽勝な機能を、あえてコーディングだけで実現する、というのは面白い。

@akashi_keirin on Twitter