第12回 広がる世界〜共有ライブラリを使ってみよう「3.並び替えとCSV?」

12−3 並び替えとCSV?

つぎは、データの並び替えなどをしてみましょう。これは大量のデータを並び替えする時に威力を発揮します。
並び替え、というとプログラミング本には必ず登場する要所の1つです。クイックソートやバブルソートなど、色々なアルゴリズムに基づいた並べ替えを実習するのですが、幸か不幸か、このNSBSystemLibには、並べ替えの機能が既に備わっています。
並べ替えの機能は、このライブラリのVer.1.4になってから追加された機能のようで、リファレンスでは下のほうに書かれています。
機能が幾つかあるようですが、見た目に分かり易い「リストオブジェクトの中身を並べ替える」というモノを試してみることにしました。他は、この例の応用と思いますので、各自で取り組んでみて下さい。

まず、並べ替え前後のリストボックスの状態が見たいですから、2つのリストオブジェクトを用意します。
これらのリストに何らかの値を入れなければいけませんから、フィールドを1つと挿入ボタンを1つ、そして、実際に並べ替えをするためのボタンを1つ用意しました。

  

最初に、リストボックスの中身をクリアしたいので、FormのAfterに次のコードを書いてみました。
	Sub Form1003_After()
    
	    List1004.Clear
	    List1005.Clear
    
	End Sub
左が1004、右が1005です。
そして、どちらのリストにも、フィールド(1007)の内容が挿入されるように、ボタンのイベントコードは、このコードにしました。
	Sub object1006()
    
	    List1004.Add Field1007.text
	    List1005.Add Field1007.text
    
	End Sub
簡単ですが、これで、フィールドに入れた値を2つのリストボックスに追加挿入するプログラムが出来ました。Basic BASICも12回目ですから、この辺りまではサラりと済ませても良いでしょう。
とはいえ、あまりにも簡単に出来てしまいましたので、動作が不安です。実際に動作させて見ましょう。

  

無事に動作するようです。フィールドに入力した文字が、ボタンをタップすると2つのリストボックスに追加されます。
しかし、実際にこの作業でデータを入れていこうと思うと、これが随分と面倒な作業である事に気付きました。フィールドに文字列を書いて、ボタンをタップして、フィールドの文字列を消して、また別の文字列を書いて、ボタンをタップして・・・データを10個も入れると、疲れてしまいます。
使ってからはじめて気が付いた、ってヤツですね。意外とそういう発見がありますので、分かっていても試してみる、という姿勢も重要です。中華料理の周富徳でしたっけ「味見が大事よ」って言っていたのは。
そんな面倒を解消するために、最初はプログラム中からダミーデータを適当に作って入れる、という方法も考えましたが、このライブラリの中にある関数で使えそうなものを発見しましたので、これを試すことにしました。

特定の文字列で区切られたデータ、少し具体的にいえば、CSVなどがそれに当たりますが、これから、1つ1つを要素として取り出すことが出来れば、データは比較的簡単に扱う事が出来ます。
しかし、これを、Visual BASIC流のSplit()関数を持たないNS Basicで実現しようとすると、InStr()などで、カンマの位置を先頭から探し出し、1つずつMid()などを使って取り出す等の方法を考えなければなりません。しかし、このライブラリ中に、Split()に近い関数を発見しました。文字列関数のDelimitedItem()です。
	DelimitedItem()

	item = NSBSystemLib.DelimitedItem(inputStr, delimiter, nbr)

	特定のデリミタ(分割文字)を含む文字列から、デリミタで分解した指定した位置の文字列を返します。 
もうすこし、簡単な説明にしましょう。次のようなCSVデータがあるとします。
	abc,XYZ,mizuno-ami,Ohyoi3
この文字列を、カンマで区切られたデータと見なして、その3番目のデータ「mizuno-ami」を得るには、
	inputStr = "abc,XYZ,mizuno-ami,Ohyoi3"
	delimiter = ","
	nbr = 3

	item = NSBSystemLib.DelimitedItem(inputStr, delimiter, nbr)
とします。これで、変数itemには「mizuno-ami」が代入されます。便利なのか不便なのか、この時点では判断出来ませんが、勝手に「,」で区切ったデータと見なして、その任意の位置のデータを取り出せるのは、便利なことだと思います。
まぁ、分割した結果全てを配列として返すSplit()関数よりは不便でしょうが、使い方によっては、同じ事が可能です。
先ほどのサンプルに、もう1つフィールド(1011)を追加しましょう。

  

挿入ボタンのコードを次のように改造します。
	Sub object1006()

	    Dim item as String
	    Dim inputStr as String
	    Dim delimiter as String
	    Dim nbr as Integer

	    inputStr = field1007.text
	    delimiter = field1011.text

	    nbr = 1

	    Do 
	        item = NSL.DelimitedItem(inputStr, delimiter, nbr)
        	If item=delimiter Then
	            Exit Do
        	End If

	        list1004.Add item
	        list1005.Add item
        	nbr=nbr+1
	    Loop

	End Sub
このサンプルは、カンマによって区切られた文字列を変数nbrを使って、1番目から順番に取り出し、リストに順次代入する、というものです。
この繰り返しは、DelimitedItemから返された文字列が、分割文字列(delimiter)と同じであれば、指定した位置のデータがない、ということなので、ループを抜けて終了しています。これで、簡単にCSVを分割できましたね。
指定された位置にデータがない時に、分割文字列が返されるのがミソのようですが、とても便利に分割をする事が出来ます。もちろん、データベースの1レコードにCSV形式でデータを入れておき、delimitedItem()を使えば、簡単に分割する事が出来るでしょう。
実行してみると、一発分解OKですね。

  

さて、サンプルの方は、データ入力が簡単になりましたので、早速、並べ替えをしてみましょう。
相変わらず、説明があまり分かり易くないので、クイックソート(ListQSort)のサンプルプログラムをコピー&ペーストして使ってみましょう。
	Sub object1009()
	    Dim objID as Integer
	    Dim error as Integer
	    Dim maxItems as Integer
	    Dim itemType as String
	    Dim numItems as Integer
	    Dim reverseSort as Integer
	    Dim caselessSort as Integer

	    maxItems = 100

	    itemType = "string"

	    error = NSL.SortInit(maxItems, itemType)

	    If error <> 0 Then
	        MsgBox "SortInit error = " + Str(error)
        	Exit Sub
	    End If

	    objID = 1005

	    reverseSort = 0
	    caselessSort = 0
    
	    numItems = NSL.ListQSort(objID, reverseSort, caselessSort)

	    MsgBox str(numItems)
	End Sub
これを「並替え」ボタン(1009)のイベントコードとして入力します。一応、どのリストオブジェクトを並び替えるのか、という事をそのオブジェクトのIDで指定する、ということが分かりましたので、変数objIDに右側のリストボックスのID、1005を代入してみました。また、ListQSort()の戻り値が、並び替えられたアイテム数、ということですので、確認のために、最後にMsgBoxを追加してみました。
さて、早速、同じようなサンプルで実行してみましょう。

  

並び替えたアイテム数4件が表示されました。そして、

  

どうでしょう?例が悪いので、ちょっと見難いですが、右側のリストボックスは、キチンと並び替えられています。
この関数は、リストボックスのID番号、昇順・降順を指定するreverseSortと、大文字・小文字の区別の有無を指定するcaselessSort、これら3つの引数を指定するだけです、それだけで、簡単にクイックソートを扱う事が出来ます。
ただし、並び替え機能を使う前に、必ず初期化しなければならない点だけ忘れないようにして下さい。
並べ替えの関数を初期化しているのは、
	    maxItems = 100

	    itemType = "string"

	    error = NSL.SortInit(maxItems, itemType)
この部分で、この場合は、最大100個の文字列データを扱いますよ、という初期化をしています。
具体的な動作は、ともかくとして、一時的に並べ替えデータを保持するために領域を予約しているんだなぁ、という程度に理解しておいてください。
この一時領域は、新たにSortInit()で初期化されるか、プログラムが終了してライブラリが使われなくなった時点で、開放されます。

ちょっと実装が面倒だった並べ替えですが、このようにライブラリを使うことで、とても簡単に利用できるようになりました。この並び替え機能だけでも、ライブラリを使うメリットがあるのではないかと感じる方もみえるのではないでしょうか。


前へ     目次へ     次へ

第12回 広がる世界〜共有ライブラリを使ってみよう「3.並び替えとCSV?」