for ループ外
> for ループ内1 '調査
> ...
> next
> for ループ内2 '出力
> ...
> next
> 初期化
>next
> >これを、改めて、最初に示したものレベルまで簡略化して表現すると、以下のとおり。 > >
for ループ外
> 調査
> 出力
> 初期化
>next
> >今回いただいたご質問は、要は、「さて、↑これでどうか?」ということです。 > >では、どうでしょうか。 >ご自身で考えて、またコメントいただければと思います。いっしょに考えましょう。 > >なお、今回一点だけ指摘しておくと、以下の2つの変数宣言は、僕なら、「for ループ外」より前に持っていきます。 > >Dim vKeys As Variant >Dim vItems As Variant > >では、どうしてか? >これについても、ご自身で考えみてて、またコメントいただければと思います。 > >まずは、以上のとおりです。 > > >>お世話になっております。 >> >>連想配列について質問です。 >> >>Chap02-71のSheet2の演習で、取引金額をH列にも追加して、 >>KeyはB列ひとつなんですが、ItemがG列とH列です。 >> >>書き出し先は、KeyがI列、ItemがG列→J列、H列→K列です。 >> >>とりあえず正しく反映しますが、以下コードで問題ないか、 >>アドバイスをお願いします。 >> >>なんとなくですが、removeallでいったんクリアにするので、 >>それが悪さしないのか心配です。 >> >>Sub GetCount() >> Dim dic As Scripting.Dictionary >> Set dic = CreateObject("Scripting.Dictionary") >> >> Dim c As Long >> Dim r As Long >> Dim st As String >> >> For r = 0 To 1 >> For c = 0 To Range("A" & Rows.Count).End(xlUp).Row - 2 >> st = Range("B2").Offset(c).Value >> If dic.Exists(st) Then >> dic.Item(st) = dic.Item(st) + Range("G2").Offset(c, r).Value >> Else >> dic.Add (st), Range("G2").Offset(c, r).Value >> End If >> Next >> >> Dim vKeys As Variant >> Dim vItems As Variant >> vKeys = dic.Keys >> vItems = dic.Items >> For c = LBound(vKeys) To UBound(vKeys) >> Range("I2").Offset(c).Value = vKeys(c) >> Range("J2").Offset(c, r).Value = vItems(c) >> Next >> dic.RemoveAll >> Next >> >>End Sub >> >
平吹 敦史さんの投稿
(投稿ID: 2942)
表示をシンプル化すると、理解しやすくなりますね。
さて、以下2つについてですが、マクロの実行結果は変わりません。
結果だけみれば、要は配列の中身をクリアにして、最初のループをむかえられれば良いので、
どちらでもよい気がします。
ただ、初期化というくらいですので、コードの最初にないと理解しにくい、
うまり可読性が低くなるとうことでしょうか?
①
②
>なお、今回一点だけ指摘しておくと、以下の2つの変数宣言は、僕なら、「for ループ外」より前に持っていきます。
>
>Dim vKeys As Variant
>Dim vItems As Variant
これについても、for ループ外でも内でも結果は変わりません。
そうすると、可読性でしょうか?
ループ外にもっていくと、見た目はすっきりします。
また、冒頭にバリアント型のオブジェクト変数があるよ、と明示する為でしょうか?
マクロの実行結果が同じなのに、コードを書く場所が複数あり得る。
そんな時に、何をもって、その場所に書くのか・・・
こんな感じしか今の私にはわかりません。
よろしくお願いします。
>平吹 敦史 さん:
>
>おはようございます。
>
>初期化のタイミングをどこにするか?ということですね。
>
>基礎編フォローアップでその基本を解説している問題があります。
>
>○出現回数を数える。CountIf関数がやっていることをマクロで書くと?
> https://forum.pc5bai.com/lesson/page/150
>
>以下、この動画内での解説をさらにシンプルに表現してみます。
>上記動画での解説は複数のものについて調査→出力するときのパターンのあくまで一例ですが、要は、こういうこと↓です。
>
>
>
>この調査の部分で forループを使っています。以下のとおり。
>
>
>
>もちろん、出力にforループを使うことが必要になる場合もあります。すると、以下。
>
>
>
>↑これは、今回の連想配列の課題のパターンですね。
>
>さて。
>平吹さんが今回書かれたコードは、こう↓なっていますね。
>
>
>
>これを、改めて、最初に示したものレベルまで簡略化して表現すると、以下のとおり。
>
>
>
>今回いただいたご質問は、要は、「さて、↑これでどうか?」ということです。
>
>では、どうでしょうか。
>ご自身で考えて、またコメントいただければと思います。いっしょに考えましょう。
>
>なお、今回一点だけ指摘しておくと、以下の2つの変数宣言は、僕なら、「for ループ外」より前に持っていきます。
>
>Dim vKeys As Variant
>Dim vItems As Variant
>
>では、どうしてか?
>これについても、ご自身で考えみてて、またコメントいただければと思います。
>
>まずは、以上のとおりです。
>
>
>>お世話になっております。
>>
>>連想配列について質問です。
>>
>>Chap02-71のSheet2の演習で、取引金額をH列にも追加して、
>>KeyはB列ひとつなんですが、ItemがG列とH列です。
>>
>>書き出し先は、KeyがI列、ItemがG列→J列、H列→K列です。
>>
>>とりあえず正しく反映しますが、以下コードで問題ないか、
>>アドバイスをお願いします。
>>
>>なんとなくですが、removeallでいったんクリアにするので、
>>それが悪さしないのか心配です。
>>
>>Sub GetCount()
>> Dim dic As Scripting.Dictionary
>> Set dic = CreateObject("Scripting.Dictionary")
>>
>> Dim c As Long
>> Dim r As Long
>> Dim st As String
>>
>> For r = 0 To 1
>> For c = 0 To Range("A" & Rows.Count).End(xlUp).Row - 2
>> st = Range("B2").Offset(c).Value
>> If dic.Exists(st) Then
>> dic.Item(st) = dic.Item(st) + Range("G2").Offset(c, r).Value
>> Else
>> dic.Add (st), Range("G2").Offset(c, r).Value
>> End If
>> Next
>>
>> Dim vKeys As Variant
>> Dim vItems As Variant
>> vKeys = dic.Keys
>> vItems = dic.Items
>> For c = LBound(vKeys) To UBound(vKeys)
>> Range("I2").Offset(c).Value = vKeys(c)
>> Range("J2").Offset(c, r).Value = vItems(c)
>> Next
>> dic.RemoveAll
>> Next
>>
>>End Sub
>>
>
小川慶一さんのコメント
(コメントID: 4422)
おはようございます。
結論から言うと、VBでは結果的にどちらでもOKですが、一般論としては、ループに入った直後に初期化、のほうが美しいですね。
というのは、発展編1でもお伝えしているかと思いますが、VBでは、変数は宣言した直後に自動的に初期化までしてくれるので。
CやJavaのような言語では、変数は宣言しただけでは使えず、さらに、初期化を自分でする必要があります。
つまり、「初期化してくれる」というのは、プログラミング言語一般に言える当然の実装ではない、ということです。
そのとき、より汎用的な、言い換えれば、よりITリテラシーの高いコーディングのスタイルはどちらか?と言えば、それは、変数に値を代入する前に初期化のステップを入れるという方になります。
>>なお、今回一点だけ指摘しておくと、以下の2つの変数宣言は、僕なら、「for ループ外」より前に持っていきます。
>>
>>Dim vKeys As Variant
>>Dim vItems As Variant
僕が演習の回答として示しているコードで、ループの中で変数宣言しているものがひとつでもあったでしょうか。
こびとちゃんの立場になって考えてみてください。
ループの回数だけ変数を改めて宣言するか?一度で済ませて、その変数を使いまわすか?の違いです。
>マクロの実行結果が同じなのに、コードを書く場所が複数あり得る。
>そんな時に、何をもって、その場所に書くのか・・・
純粋に経験不足かと思います。
基礎編からの演習をくり返し、そして、実務でもマクロをガンガン書いてください。
基礎編~発展編1の演習を、考えるために手を止めること一度もなくスラスラと解けるようになったころには、こういう疑問が出てもたいして悩まないうちに自分でアイデアを出して解決できるようになるかと思います。
あと、複数の書き方がある場合の方法選択については、以下の記事も参考になるかと思います。
http://www.exvba.com/blog/?p=4378