アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんばんは。
リストボックスでのマルチセレクトで選択した項目を削除する
方法で悩んでいます。
(リストボックスで3項目選択したとして、この3項目を削除する方法)

解答は現在勉強している本に掲載されているのですが意味が分からず。

解答のコードの方にはリストを後ろから削除しているみたいなのですが、
前から削除しても大丈夫だと思いやってみましたが、エラーが出てしまいます。

解説には、先頭から削除するとその時点でリストのインデックス値がずれて
しまう。と書いてあるのですが、後ろから削除しても一緒だと考えこんでいます。

解答コード
**********************************************************
Private Sub Command2_Click()
Dim i As Integer

'選択状態(Selected=true)の項目だけ削除
For i = List1.ListCount - 1 To 0 Step -1
If List1.Selected(i) = True Then
List1.RemoveItem i
End If
Next i

End Sub
*********************************************************

と言う解答コードを自分は、前から削除するように

自分なりのコード
*********************************************************
Private Sub Command2_Click()
Dim i As Integer

For i = 0 To listcount-1
If List1.Selected(i) = True Then
List1.RemoveItem i
End If
Next i

End Sub

*************************************************************
で作成してみましたが、やっぱりエラーが。

なぜ、前から削除するとエラーになってしまうのか、
もう少し具体的に教えてくれると助かります。

よろしくお願いします。m(__)m

A 回答 (5件)

こんにちわ。



コードの処理に沿って順番に説明しますね。
リストの内容はA~Eの5個あり、BとDを選択した状態だとします。

*リストの内容**
1|A
2|B ←選択
3|C
4|D ←選択
5|E
**************

これを解答コードのように後ろから削除する場合、5から1まで繰り返し判定するわけですが、
1回目(5):Eは選択されていませんので何もしません。
2回目(4):Dが選択されているので削除します。

*リストの内容**
1|A
2|B ←選択
3|C
4|E
**************

3回目(3):Cは選択されていませんので何もしません。
4回目(2):Bが選択されているので削除します。

*リストの内容**
1|A
2|C
3|E
**************

5回目(1):Aは選択されていませんので何もしません。
結果、以下のようなリストになり正常に動作します。

*リストの内容**
1|A
2|C
3|E
**************

同じ様にmineral01さんのコードのように前から削除する場合、
1回目(1):Aは選択されていませんので何もしません。
2回目(2):Bが選択されているので削除します。

*リストの内容**
1|A
2|C
3|D ←選択
4|E
**************

3回目(3):Dが選択されているので削除します。
(この時点でインデックスがずれているためCの判定が飛ばされてしまいます。)

*リストの内容**
1|A
2|C
3|E
**************

4回目(4):4番目の要素が無いためエラーになります。
この段階ではもうリストの内容が3つしかないために、4番目の内容を取得しようとするとインデックスエラーとなってしまいます。

どうしても前から削除したい場合は、以下のコードで大丈夫だと思います。
mineral01さんのコードに追記してみました。
*********************************************************
Private Sub Command2_Click()
Dim i As Integer

For i = 0 To List1.listcount - 1
If List1.Selected(i) = True Then
List1.RemoveItem i
i = i - 1
End If
If i >= List1.ListCount - 1 Then
Exit For
End If
Next i

End Sub

*************************************************************

長文なってしまい、申し訳無いです。参考になれれば幸いです。
    • good
    • 0
この回答へのお礼

hersheさん、とても理解しやすい説明ありがとうございます。
おかげさまで理解できました。
リストを前から、判定してしまうと、
インデックス値(iの値)がずれてしまったために
判定処理が飛ばされてしまうんですね。

リストに最後の値がないにもかかわらず、リストの内容を取得しようとして
いるためにエラーが出ることがとても理解できました。

後ろから判定をすると全ての値を効率よく(インデックス値をずらすことなく)、
判定できるんですね。

また、前からの処理での削除方法ありがとうございます。
本当に勉強になりました。
iの値を引いてあげる点と、現時点でのインデックス値(iの値)を判定して
あげる処理がポイントだと分かりました。

本当に、分かりやすい説明ありがとうございました。m(__)m

お礼日時:2002/07/26 02:40

BlueRayです。

少しばかり追加解説です。

ダルマA
順|○|
1|A|
2|B|
3|C|
4|D|
5|E|

リストの順番は、下から1,2,3,4,5です。
そして、ダルマが一番最後を表しています。
    • good
    • 0

ダルマ落しで表現しますね。

○をダルマでと思ってください(^^;

ダルマA  ダルマB
順|○|  順|○|
1|A|  5|A|
2|B|  4|B|
3|C|  3|C|
4|D|  2|D|
5|E|  1|E|

解答コードがダルマAで、mineral01さんのコードがダルマBです。
順と書いてある通りに崩していきます。
では、参考までに1番目を崩してみましょう。
ダルマA  ダルマB
順     順
1|○|  5|○|
2|B|  4|A|
3|C|  3|B|
4|D|  2|C|
5|E|  1|D|

次に2番目を崩してみましょう。
ダルマA  ダルマB
順     順
1     5
2|○|  4|○|
3|C|  3|A|
4|D|  2|B|
5|E|  1|D|

以下5番目まで崩して、ダルマを一番下に落とすことが出来るのはどちらですか。
明らかにダルマAですね。ダルマBは4回目で何も出来ないですね。

連続項目削除は、この様に最後までダルマを落とせる様にしなくてはいけないんです。

わかりにくかったら、補足してください。ではでは。
    • good
    • 0
この回答へのお礼

説明ありがとうございます。
皆様の説明で、理解するとことができました。
かなり悩んでいたので、本当に助かりました。
ありがとうございます。

お礼日時:2002/07/26 02:44

こんにちは。

maruru01です。

リストを1つ削除すると、その度にそれより後ろ(Indexが大きいもの)のIndexが変更(1つずつ繰り上がる)されてしまうからです。
前(Indexの小さい方)から削除すると、後ろの削除対象のリストのIndexが変更(1つ繰り上がる)されるので、選択したものと別のものを削除したり、エラーになったりします。
後ろ(Indexの大きい方)から削除すれば、その後ろのIndexが変更されても構わないわけです。(削除対象が前(Indexが小さい方)にしかないので。)

では。
    • good
    • 0
この回答へのお礼

後ろから削除することによって、削除対象が小さい方にしかないので、
全て効率よく(index値をずれなくして)削除できるんですね。
また、後ろからだと比較したインデックスが変更されても大丈夫と言うことが
分かりました。

説明、本当にありがとうございました。m(__)m

お礼日時:2002/07/26 02:49

下記の「繰り上がりがあるときの」ロジックを考えてみられては。


下記(2)の下からの繰り上がりを考えに入れてないのでは。(下記でdeleteとかA(i)としているのは仮想の表現で、リストの場合RemoveItemです。セルの削除等の場合も念頭に入れているため)
5つアイテムがあったとして、
(1)後ろ(下と言いますか)から、3つ削除するときは、
上から5番目削除、次に上から4番目削除、次に上から3番目削除・・となります。iは5,4,3・・・です。
for i=5 to 3 step -1
a(i).delete
next i
(2)先(上と言いますか)から、3つ削除する時は、
まず上から1番目削除、「下から繰り上がってくるので」、2番が1番に繰り上がってくるので、次も1番を削除すればよい。次も同じ。
for i=1 to 3
a(1).delete
next i
    • good
    • 0
この回答へのお礼

説明ありがとうございました。
プログラミングの奥の深さを新ためて実感しました。
まだまだ、勉強不足です。

本当にありがとうございました。m(__)m

お礼日時:2002/07/26 02:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A