今回は、配列の要素を削除し、配列をリサイズしてしまう方法について書きました。
○配列の要素を削除
——————
この方法はすごく面倒だったので、こちらで作り直ししております。
[UWSC]配列の要素の削除と挿入・追加[参照渡し使用]
——————
プログラムを作る際にはサラッと短いコードで見やすくするのが基本です。理由は、全てのステップに意味があるので、これは何だっけ?と常に再考する必要があるからです。
そのためによく使うのはループ。ループを使うにはやっぱり要素番号を指定して使える配列変数が便利です。というわけで、配列変数をもうちょっと使いこなします。
配列の要素を削除して再構築してしまう
その中で使用する関数が以下です。
この関数の中でb[]という引数a[]より一つ要素の少ない配列を宣言して、a[]の要素のうち必要なものだけをコピーするための箱として使用します。必要な部分かどうかは4~16行目のif文で判断します。また、ubound()はこちらの記事([UWSC]配列の最大要素を返す関数)で作成した自作関数で、“渡された配列の最大要素数”を返す関数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | FUNCTION arry_remove(a[],rn) j=0 DIM b[ubound(a)–1] IF rn>ubound(a) RESULT=SLICE(a,0,LENGTH(a)–1) PRINT “ポクエラー(arry_remove関数):最大要素数より大きな要素が削除指定されました。“ ELSE FOR i=0 TO ubound(a) IF (i=rn) ELSE b[j]=a[i] j=j+1 ENDIF NEXT RESULT=SLICE(b,0,LENGTH(b)–1) ENDIF FEND |
1,17行目 | 1 17 | FUNCTION arry_remove(a[],rn) FEND |
arry_remove()関数宣言: 引数a[]:削除したい要素のある配列、引数rn:削除する要素数 | ||
2,3行目 | 2 3 | j=0 DIM b[ubound(a)–1] |
以降使用する変数の初期値を代入。 配列b[]は渡された配列a[]より一つサイズの小さいものを宣言。(1要素削除する関数なので) | ||
4,7,16行目 | 4 7 16 | IF rn>ubound(a) ELSE ENDIF |
if条件文は、引数rn(:削除しろと渡された要素番号)が、削除対象の配列a[]の最大要素数より大きいかどうか。 (成り立つ)⇒ 5~6行目を実行 (成り立たない)⇒ 8~15行目を実行 | ||
5,6行目 | 5 6 | RESULT=SLICE(a,0,LENGTH(a)–1) PRINT “ポクエラー(arry_remove関数):最大要素数より大きな要素が削除指定されました。“ |
削除するべきものがないのでa[]をそのまま返す。また、使用法が間違っているのでエラーを表示。 | ||
8~15行目 | 8 9 10 11 12 13 14 15 | FOR i=0 TO ubound(a) IF (i=rn) ELSE b[j]=a[i] j=j+1 ENDIF NEXT RESULT=SLICE(b,0,LENGTH(b)–1) |
変数iを0→a[]の最大要素までループさせる。 if条件文はi=rn。つまり、指定された番号(削除したい番号)の場合。 11、12行目 全要素コピーし終わってループを抜けたら、出来上がったb[]を関数の戻り値として返す。 |
呼び出し側は(“ARRY[]”という配列を使っている場合)、
1 2 3 4 5 | dmy=arry_remove(ARRY,2) DIM ARRY[ubound(dmy)] FOR i=0 TO ubound(dmy) ARRY[i]=dmy[i] NEXT |
1行目 | 1 | dmy=arry_remove(ARRY,2) |
配列ARRY[2]を上の関数で削除します。戻り値を配列dmyに代入します。 | ||
2行目 | 2 | DIM ARRY[ubound(dmy)] |
配列ARRY[]の最大要素番号を配列dmyの最大要素番号に変更します。 | ||
3~5行目 | 3 4 5 | FOR i=0 TO ubound(dmy) ARRY[i]=dmy[i] NEXT |
配列ARRY[]へ配列dmyをコピーします。 |
使用する場合には、3ヶ所(1、2、4行目)の“ARRY”を目的の配列名に書き直します。
動作確認しながら仕様を理解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //↓★1 DIM ARRY[9] FOR i=0 TO 9 ARRY[i]=i+1 NEXT //↑★1 ↓★2 PRINT “使用前“ FOR i=0 TO ubound(ARRY) PRINT “ARRY[“+i+“]=“+ARRY[i] NEXT //↑★2 ↓★3 dmy=arry_remove(ARRY,2) DIM ARRY[ubound(dmy)] FOR i=0 TO ubound(dmy) ARRY[i]=dmy[i] NEXT //↑★3 ↓★4 PRINT “使用後“ FOR i=0 TO ubound(ARRY) ARRY[i]=dmy[i] PRINT “ARRY[“+i+“]=“+ARRY[i] NEXT //↑★4 |
2~5行目 | 2 3 4 5 | DIM ARRY[9] FOR i=0 TO 9 ARRY[i]=i+1 NEXT |
確認に使うためにARRYという配列変数に適当な値入れておく。 | ||
7~10行目 | 7 8 9 10 | PRINT “使用前“ FOR i=0 TO ubound(ARRY) PRINT “ARRY[“+i+“]=“+ARRY[i] NEXT |
目的のブロック(★3)に入る前にARRYの中身がどうなってるか表示しておく。 | ||
12~16行目 | 12 13 14 15 16 | dmy=arry_remove(ARRY,2) DIM ARRY[ubound(dmy)] FOR i=0 TO ubound(dmy) ARRY[i]=dmy[i] NEXT |
動作確認をしたい呼び出しコード。 このプログラムでは“要素数2”を削除してみようと思います。 | ||
18~22行目 | 18 19 20 21 22 | PRINT “使用後“ FOR i=0 TO ubound(ARRY) ARRY[i]=dmy[i] PRINT “ARRY[“+i+“]=“+ARRY[i] NEXT |
目的のブロック(★3)から出た後ARRYの中身がどうかわったか表示する。 |
結果 | 使用前 | 使用後 |
結果 | ARRY[0]=1 ARRY[1]=2 ARRY[2]=3 ARRY[3]=4 ARRY[4]=5 ARRY[5]=6 ARRY[6]=7 ARRY[7]=8 ARRY[8]=9 ARRY[9]=10 | ARRY[0]=1 ARRY[1]=2 ARRY[2]=4 ARRY[3]=5 ARRY[4]=6 ARRY[5]=7 ARRY[6]=8 ARRY[7]=9 ARRY[8]=10 |
元々、3が入っていたARRY[2]が削除され順に詰められました。
rnの値を変更して動きを確認してみてください。
綺麗な状態にしておきたい配列はクラスでも作ってグローバルで管理した方がよいのですが、ループの作り方の例題として配列の操作は向いてるかなと思い作ってみました。
ただ、呼び出し側が4行あり、再利用の際には3ヶ所書き換え要。と余りスッキリしないコードになってしまいました。もっとスマートなやり方誰か教えてください。
○配列の要素を削除
コメント