配列(要素1万個)の中を探す時間を短縮するために、1回探し見つかったらその要素を削除し、次に探す際はちょっと短時間で済むようにしたいと思ってます。そのために配列をコレクションに変更しようと思ってます。可能でしょうか?
詳細
商品名が1万個、セルに入力されてます。各商品に該当するファイルを開き、処理後閉じ、次の商品に移ります。開くファイル名は配列に入ってます(要素数1万個)。ファイル名の一部に商品名があるので、これを検索し順次ファイルを開きます。
Dim Files(10000) As String
Dim i as Long, j as Long
’Filesにファイル名を代入する処理が途中にあります
.
For i=2 to Cells(Rows.Count, 1).End(xlUp).Row
Name="*" & Cells(i, 4) & ".txt"
For j=1 to Ubound(Files)
If Name Like Files(j) then
'ファイル開き処理
End if
Next
Next
雰囲気だけで書いてるので、実際と違います。書き間違いで動作しない可能性が高いです。
配列に収めたファイル名があって、セルの商品名に該当するファイル名を配列から探し、開き、処理、閉じるのです。しかしながら所要時間が1個1秒未満程度ですが、結構な時間になります。
質問
配列をコレクションに変更し、1個処理が終わる度にコレクションの要素から削除していけば、探す時間は短縮されると思ったのですが、どうでしょうか?速くなるでしょうか?
No.7ベストアンサー
- 回答日時:
こんにちは。
一応、二分木検索方を知らないわけではありませんが、Excel VBA?で、そのアルゴリズムを使ったことはありませんね。あえてやればできるというだけで、それに代わるものを考えてしまいます。
スピードを比較したわけではありませんから、どちらがどうとは言えませんが、1次元配列で1万個程度なら、ワークシート関数のMatch関数を使うのが速いような気がしますね。Match関数の中身はどうなっているかは知りませんが、二分木(Binary Tree)とは同じ働きをします。それから、Quickソートは、再帰があるから、思ったほどに速くはないはずです。ワークシートのコマンドを利用したほうが速そうです。
>配列をコレクションに変更し、1個処理が終わる度にコレクションの要素から削除していけば、
コレクションというのは、入れ物が大きいオブジェクトですから、数が増えれば、その分重くなるはずです。オブジェクト群を直接操作するなら可能ですが、そうでないと使う意味はあまりありません。
なお、
sName="*" & Cells(i, 4) & ".txt" 'Name -> sName :プロパティ名を直接変数にしてはいけません。
>If Name Like Files(j) then
Filter(VBA関数, 戻り値が、見つかららない場合は、-1 になる)
Application.Match (ワークシート関数:Application.からダイレクトなのは、エラー値を排除するため。IsError や Vartype : Long で戻り値の有効性を調べる)
No.6
- 回答日時:
× 配列に入れたファイル名をセルに入れて・・・・
〇 ファイル名を格納した配列をソートし・・・・
処理の準備1・・・Excelのセルを参照し配列準備
(1)商品名も配列に。
(2)ファイル名の一部にある商品名を配列に。
(3)ファイル名も配列に。
処理の準備2・・・配列に読み込んだデータをソート
処理の準備3・・・その他の準備
本処理
GoodsCounts = UBound(strGoodsNames())
FileCounts = UBound(strFileNames())
For I=1 TO GoodsCounts
'
' I番目の商品名の処理
'
strGoodsName=strGoodsNames(I)
'
' 商品名に対応するファイル名を検索
'
’-----------------------
' バイナリーサーチ
' -----------------------
' P=検索開始位置
' S=二分木探索変数XXX
' L=二分木探索変数XXX
' M=二分木探索変数XXX
'
・・・・・
・・・・・
’-----------------------
' ファイル処理
' -----------------------
・・・・・
・・・・・
Next I
つまり、EXCEL のセルを参照し配列に読み込むのは準備工程で一回だけです。その後のソートや検索もメモリ上に行います。双方共にソートしておけば、バイナリーサーチの検索ポイントを操作することが可能です。多分、一回の検索に要する時間は1万分の1秒以下だと思いますよ。なお、ファイル処理を上記For-Next文で行うのか、それとも全てを検索後に一括して行うか?これは、後者がお勧めです。まずは、ファイル処理を一括して行うに十分なデータをセルに書き出すか、シーケンシャルファイルとして吐き出すかして成功・不成功を確認。そういうプログラムの単純化がお勧めです。
No.5
- 回答日時:
keyを指定したCollectionオブジェクトを作れば、
「For j=1 to Ubound(Files)
If Name Like Files(j) then
の判定がなくなるでしょう。当然、Loopやクイックソートやバイナリーサーチも不要でしょう。Likeの意味がよく分かりませんが、Itemに重複があるということでしょうか。
また、
「For i=2 to Cells(Rows.Count, 1).End(xlUp).Row」
については、セル範囲をVariant型の変数に一括代入すれば、以降はメモリでの処理になり、シートとのI/Oが減ることでこちらは速くなると期待されます。(数十万件の処理で劇的に速くなったこともあります)
Collectionにすると、処理速度は若干遅くなるはずで、Variant型の変数との比較はやってみないと分からないと思います。
>配列をコレクションに変更し、1個処理が終わる度にコレクションの要素から削除していけば、探す時間は短縮されると思ったのですが
よく試すことがありますが、処理が先頭から順番に行われる場合、逆に末尾から行われる場合。末尾から行われる場合は削除して意味がある? 逆に先頭からの場合は削除にコストがかからないか考える必要があるでしょう。実際のデータを見ないと何とも言えませんね。感覚的にはコレクションならほとんど差がないのではと思います。
実は、質問にある「コレクション」の意味が、「Collectionオブジェクト」なのか「Dictionaryコレクション」なのか判断付きませんでした。個人的には「Dictionaryコレクション」を使っています。当然、ソート不要で削除も可能です(処理効果は分かりませんが)。実際、行ってみるのが一番です。ご参考に。
ありがとうございます。
Likeを使う理由はファイル名がまちまちで、商品名を含むのは確実ですが他の部分が一定してないからです。likeならワイルドカードを使えるからです。重複はありません。
コレクションは過去使ったことが無いので、おそらくオブジェクトだと思います。
まずは商品名の配列への代入を試してみます。そういえば一括で変数代入出来たような記憶があります。
No.4
- 回答日時:
D列に商品一覧を準備
F列にファイル名一覧を(マクロで?その必要があるのかは?)準備
sub macro1()
dim i as long
dim myFile as string
range("F:F").sort key1:=range("F1"), order1:=xlascending, header:=xlno
for i = 2 to range("A65536").end(xlup).row
myfile = application.vlookup("*" & cells(i, "D") & ".txt", range("F:F"),1)
’ファイル開き処理
next i
end sub
まぁ騙されたと思って試してみて下さい。
現実にはブックをイチイチ開く、閉じるの方が遥かにボトルネックになりそうですが。
#あぁ、あと実際の具体的なデータの中身とかナイショなので、カンジだけでこのマクロも書いてるので悪しからず。
ありがとうございます。
ファイル名をソートしてVlookupするのが肝ですね。エクセル関数をVBA上で使用出来るのは初めて知りました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA 変数名に変数を使用したい。
-
エクセルでXY座標に並べられた...
-
C#でbyte配列から画像を表示さ...
-
Redim とEraseの違いは?
-
配列の中の最大値とそのインデ...
-
配列のペースト出力結果の書式...
-
Dir関数で読み取り順を操作でき...
-
配列をランダムに並び替えても...
-
CheckBoxの配列化
-
2次元配列でウォッチが出来ない
-
VB.NETの配列にExcelから読み込...
-
vba フィルター 複数条件 3つ以...
-
VB6からの移行したいけど、VB.N...
-
Excelのメモリ(配列)の上限は2G...
-
構造体配列の特定のメンバーをF...
-
VB6で、一次元配列と二次元配列...
-
(VBA) 配列の文字列を昇順で並...
-
配列の要素がすべてカラかどう...
-
VBA フォルダ内のファイルを、...
-
定数配列の書き方
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA 変数名に変数を使用したい。
-
エクセルでXY座標に並べられた...
-
C#でbyte配列から画像を表示さ...
-
配列のペースト出力結果の書式...
-
vba フィルター 複数条件 3つ以...
-
配列の中の最大値とそのインデ...
-
Excel2010のinputboxで複数デー...
-
Redim とEraseの違いは?
-
Excelのメモリ(配列)の上限は2G...
-
COBOLの基本的な事なので...
-
構造体配列の特定のメンバーをF...
-
Dir関数で読み取り順を操作でき...
-
構造体配列内の文字列検索のよ...
-
VBAでMODE関数をつくる
-
CheckBoxの配列化
-
Segmentation Fault (メモリ制限?)
-
定数配列の書き方
-
複数のtextboxの処理を一括で行...
-
VB.NETにて、構造体へデータを...
-
テキストボックの文字を一行ず...
おすすめ情報