• ベストアンサー

配列入れ替えの効率的方法は

VBでグローバル変数配列を3000とっています。 格納されているデータを、1つづつずらして代入し直しをやりたいのですが 配列添え字1のデータを配列添え字0にというふうに3000回のループで 処理する以外に良い方法はないでしょうか 例 for i=0 to 2999 a[i]=a[i+1]

質問者が選んだベストアンサー

  • ベストアンサー
  • haporun
  • ベストアンサー率40% (230/562)
回答No.5

>次に発生するデータを配列に追加する処理を考えていたので発生するデータが1個であれば1つずらして空きをつくりそこに代入しようと考えていました。 それならやはりリングバッファが目的にかなっているではないですか。 X = (X + 1) Mod 3000 '最初の添え字は最後になる a(X) = NewData '最初にデータを追加 Debug.Print a(X + n) 'n番目のデータを表示する こういうのがアルゴリズムというものです。 ちなみに、"補足" を利用した場合、1つのところに書くとすべての回答者にメールが行くので、同じことを書く必要はありません。

mehiro2
質問者

お礼

VBが初心者で申し訳ございませんでした。 リングバッファというものが知りませんでしたので 調べてみます。 有難うございました。

その他の回答 (6)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.7

本質問の解答にはならないかもしれませんが、有名な「リングバッファー」というデータ構造について、読んで考えて見られては。何かの参考になるかも知れない。 http://www5c.biglobe.ne.jp/~ecb/c/14_06.html など、リングバッファーでWEB検索する。また「データ構造」の教科書などを見る。Javaでは、この名のクラスも あります。 本質問は(可能なら)配列(ファイルレコード?)の後ろの方から逆読みをして、自分の土俵の配列の後ろへ追加していけば、元ファイルと同じ順になり処理スタートとしてはそれで良いのではないのでしょうか。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.6

#3のものです。 >リアルタイム処理で・・・ リアルタイム処理かどうかの問題は関係無いと思います。 >1個であれば1つずらして空きをつくりそこに代入しようと・・・ 普通は配列には後ろ(使用配列要素数が最大の次に)にデータを追加する ものではないでしょうか。 それに対し本件では第1要素a(1)に追加しなければならない理由こそ明らかにすべきだと思います。その必然性を解答者が納得すれば、答えも最適なものが出やすいと思います。

mehiro2
質問者

補足

質問が不備で大変御迷惑お掛けしました。 ややこしい文になってしまわないかと心配して簡略になってしまいました。 具体的には、以下のようなことをやろうとしていました。 Aテーブルに日付と座標データが一定時間毎にレコードが作成されていきMAX3000レコードになったら一番古いレコードが削除されて新しい日付と座標データが一番最後に追加される処理が別で動いています。 そのAテーブルからデータを読み出して、配列に格納してグラフ表示をさせるのが目的です。データレコードが自動で更新されているので、その都度最初から読み直せば良いと思うのですが、追加されたデータだけを読んで配列に追加できないかな? と考えていました。(既に読み込んでいるデータを再度読まなくても済むように) 追加する配列要素は最大の次です。ちなみにSQLで読み込みます

  • haporun
  • ベストアンサー率40% (230/562)
回答No.4

C的な考え方ですが、インデックス何番目が、扱うときの0番目であるかをメモればいいのではないでしょうか? 適当な変数Xに最初の要素の番号を入れるのです。 アクセスするときは常に((X+n) Mod 3000)でアクセスします。 そうすれば、データを移動することなく、データの番号をずらすことができます。 データ移動後のアクセスがあまりに多い場合は、アクセス時の計算量が増えるので、効率が良いかどうかは微妙です。 しかし、アクセス数が3000回に満たないなら、この方法はお得です。

mehiro2
質問者

お礼

有難うございました。 リングバッファを見てみました。 こうゆう考え方があるのですね、とても勉強になりました。

mehiro2
質問者

補足

早速のお返事有難うございました。 説明不足で申し訳ございません。 リアルタイム処理で次に発生するデータを配列に追加する処理を考えていたので発生するデータが1個であれば1つずらして空きをつくりそこに代入しようと 考えていました。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.3

配列要素3000と言えば(メモリーが少なかった)昔なら相当なレコード量で、配列に持つなど考えられなっかたです。 もう線形で持つのは止めて、適当な「構造」を配列部分に持ちこむべきではないでしょうか。例えばHeap,Treeなど。 なぜ「ずらす」必要があるのか。まず考えついたロジックで安易にやって居ないか考えて見るべきで、その最適ロジックが無いかこそ質問すべきことではないのでしょうか。見当外れだとお許し下さい。 それと、「ずらしたい」ときは最後の方からやらないとダメでは。 × for i=0 to 2999 a[i]=a[i+1] ○ For i=2999 to 0 Step -1 a(i+1)=a(i) Next i

mehiro2
質問者

お礼

有難うございました。 ロジックの考え方が悪いのでしょうね? データの追加は、配列要素の最大値に入れますので 配列要素の最大値に空きを作ります。 ずらす方法は、最大値から行なうのですね 大変勉強になりました。

mehiro2
質問者

補足

早速のお返事有難うございました。 説明不足で申し訳ございません。 リアルタイム処理で次に発生するデータを配列に追加する処理を考えていたので発生するデータが1個であれば1つずらして空きをつくりそこに代入しようと 考えていました。

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.2

処理速度についての問題でしょうか? だとするとソートプログラムでもない限り 配列を入れ替えるというのは無駄なように思います。 配列を読む方でiの値を動かす方がいいでしょう。 特にVB6ではそういった単調作業が苦手のようです。 VCで作ったDLLにでも配列を渡せば、3000個程度の long型であれば瞬時ですけどね。

mehiro2
質問者

お礼

有難うございました。 Dosの頃にcはやったことがありましたが VBは未だ初心者です

mehiro2
質問者

補足

早速のお返事有難うございました。 説明不足で申し訳ございません。 リアルタイム処理で次に発生するデータを配列に追加する処理を考えていたので発生するデータが1個であれば1つずらして空きをつくりそこに代入しようと 考えていました。

  • maruru01
  • ベストアンサー率51% (1179/2272)
回答No.1

こんにちは。maruru01です。 コレクションを使う方法があります。 使用方法はすでにご存知かも知れませんが、 Dim myCollection As New Collection と宣言して、 myCollection.Add Item:=a とコレクションに追加していきます。 追加した順に1からインデックスがつきます。 そして不要なデータを、 myCollection.Remove i (iはインデックス番号) と削除すると、削除された分インデックスが前に詰められます。 ただし、追加順が不定の場合はそのまま使えないので、とりあえず配列に入れておいて、全部入れた後で、 For i = 1 To 3000   myCollection.Add Item:=Hairetu(i - 1) Next i と、まとめて追加するか、 For i = 1 To 3000   myCollection.Add Item:="" Next i みたいに、ダミーデータで追加しておいて、 myCollection(100) = "a" などと中身を後で代入するかです。

mehiro2
質問者

お礼

補足で大変御迷惑をお掛けしました。 コレクションコントロールでは、 少し使ったことがありますが未だ勉強不足です 有難うございました

mehiro2
質問者

補足

早速のお返事有難うございました。 説明不足で申し訳ございません。 リアルタイム処理で次に発生するデータを配列に追加する処理を考えていたので発生するデータが1個であれば1つずらして空きをつくりそこに代入しようと 考えていました。

関連するQ&A

  • 配列の結合?について

    . . Dim GetDate for i=startYear to lastYear GetDate = obj.xxxx i = i + 1 next . . このような形で年度別にGetDateに配列でデータを格納しています。 この年度別に作られる配列を一つの配列変数に代入したいのですが、 どうすればよろしいでしょうか?

  • 配列を使わずに、数字(連番)を使用した変数に値を代入したい。

    配列を使わずに、数字(連番)を使用した変数に値を代入したい。 お世話になっております。 配列を使わずに、数字(連番)を使用した変数($a1,$a2,$a3・・・)に、 forループを使って、値を代入したい。 #================================= for($i;$i<10;$i++){ $a??? = 10; #←ここがわかりません。 } #================================= どなたかご存知の方、ご教授ください。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • 配列長参照のオーバーヘッド

    for等ループでループ終了条件に配列長を使用する場合、配列長を毎回参照する場合と一旦変数に格納して参照する場合、定数を使用する場合と処理速度の差はありますか? つまり 1、for( int i = 0; i < array.length; i++ ) { ... } 2、for( int i = 0; i < len; i++ ) { ... } *(int len=array.length) 3、for( int i = 0; i < 10; i++ ) { ... } *(int[] array = new int[10]) forループ内の処理のメモリ使用量の多寡は不明で、毎ループで読み取られる全ての変数はコンピュータのキャッシュに残るかどうかは不明だとします。

    • ベストアンサー
    • Java
  • [arduino]数値の大きなデータを二次配列へ

    シリアル通信で得たデータを二次元配列へ格納するために、 以前では、 if(Serial.available()>120){ for(int k=0;k<8;k++){ for(int l=0;l<15;l++){ //読み込んだ値を配列に代入 matrix[k][l]=Serial.read(); } } } このようなやり方で読み込んだ値を二次元配列に代入していたのですが、 128個以上のデータを扱いたい場合、Serial.availableでは保持できず、困っています。 方法として、 (1)一つずつデータを読み込み、128回ループを繰り返し配列に貯めていく。その後配列を2次元配列に代入する。 (2)一つデータを読みこんだら二次元配列の1行目1列目のドットに格納、もう一つデータを読みこんだら二次元配列の1行目2列目のドットに格納…というように、 読みこんだデータをそのまま二次元配列のそれぞれの場所へ格納していく。 というような二つの方法を思いついたのですが、 (1)の方法では、配列にデータを貯蓄していくコードをこのように↓書いたのですがうまくいかず、 for(int i=0;i<128;i++){ if(Serial.available()>0){ data[128] = Serial.read(); } } (2)の方法では、データを二次元配列のそれぞれの場所へ格納していく指定方法が分かりませんでした。 正しい書き方や、良いアイデアをお持ちの方がいましたら、是非御教授お願いします。

  • 配列のbindValue方法について

    <環境> サーバーOS:CentOS webサーバー:apache データベース:MySQL PHP5.2 現在、上記の環境でwebアプリを作成しています。 データベースにデータを登録する際にPDOを使用しているのですが、 二次元配列に格納されているデータを bindValue() できずに困っています。 データが多く、個数もその都度変化するので、二次元配列に格納しています。 簡易的ではありますが、以下のようなソースコードになります。 <ソースコード> $dataArray → データが格納されている二次元配列 $columns = array(':id', ':name'); → プレイスホルダー名を格納している配列 for($i = 0; $i < count($dataArray); $i++) { $stt = $dataBase -> prepare('insert into tb_test(id, name) values(:id, :name)'); for($j = 0; $j < count($dataArray[ i ]); $j++) { $stt -> bindValue($columns[ $j ] ,$dataArray[ $i ][ $j ]); } $stt -> execute(); } 二次元配列の1行分のデータをループで bindValue() してから execute() で実行しています。 これを二次元配列の行数回繰り返しています。 apacheのエラーログには特に何も表示されていませんが、 登録処理ができません。 このような forループ では実行できないのでしょうか?

    • 締切済み
    • PHP
  • Perlの初歩的な質問・・・

    @data に大量のデータが格納されていると仮定して、次のようにループ処理するとします・・・ for($i = 0 ; $i < @data ; ++$i){ @XXX = split(/\t/, $data[$i]); } このように @data のデータをさらに細かく配列化して @XXX に代入したいのですが、ループのたびに @XXX の名前を XXX0 , XXX1 , XXX2..... とするには、どうしたらよいのでしょうか。

    • ベストアンサー
    • Perl
  • PHPで配列の最も小さいもの3つを取り出す方法

    PHPで配列のソートが出来ずに困っています 今 $a[2]=10 $a[10]=2 $a[3]=30 $a[22]=20 $a[9]=4 $a[53]=29 ・ ・ ・ のような配列があり、これを配列の値の小さいものから順に3つ取り出したいのですが、どの様にしたらよいでしょうか? 具体的には $a[10],$a[9],$a[2] という形で取り出したいです 最終的にはそれぞれの添え字を他の変数に代入した形にしたいです $b[1] = '10'; $b[2] = '9'; $b[3] = '2'; みたいなかんじです どなたかご解答いただければと思います どうぞよろしくお願いいたします

    • ベストアンサー
    • PHP
  • VBの配列について

    VB6.0について質問です。 データベースにある1レコードの情報を一括して取得し 変数に配列化して格納したいのですが可能ですか? データベースはAccessです。 DAOで接続を考えております。 以下のソースを試したのですが駄目でした><; dim ITEM_A() For tmp1 = 0 To ds.Fields.Count - 1 Step 1 ITEM_A = Replace(ds.Fields(tmp1).Value, vbCrLf, "") Next ITEM_A(0)=data1 ITEM_A(1)=data2 ITEM_A(3)=data3 ITEM_A(4)=data4 以上のように格納したいのでお願いします><

  • 配列の受け渡し

    こんばんは。 あるページで使用した配列を他のページでも使いたいのですが、 こういう配列を格納した変数の受け渡しって出来るのでしょうか? 普通の変数のデータを受け渡したかったら <input type="hidden" />で直接valueに変数の値を入れれば良いですが、 配列だと自分では以下のように愚直にやる方法しか分かりません。 もっとちゃんと渡せる方法ってあるのでしょうか? <?$a=array(1,2,3,4,5);?> <? for($i=0;$i<count($aaa);$i++){ ?> <input type="hidden" value="<?=$aaa[$i]?>" name="hoge[]"/> <?}?>

    • ベストアンサー
    • PHP
  • 【配列の保存&書き込み】

    配列を使って保存&読み込みをしたい! しかし、単純な変数を使った保存、読み込みしか サンプルが見つからなくて(汗 それで質問させて貰います。 (1)変数kirokuの配列作成 (2)記録したデータが無いかチェック (3)分岐→(4)【データが存在】→(6)【データが無い】 (4)データが存在するなら変数のすべて呼び出し  kiroku(3)まで。 (5)データが無いなら配列にすべて"0"を代入。  kiroku(3)まで。 ↓【自分で少し作ったソース】 //変数 kiroku = new Array(); //既にデータが保存しているかチェック if (savedata.data.kiroku[0] != null) { //特に処理なし } else { //データが存在していれば初期値0に設定。 for (i=0; i<3; i++) { kiroku[i] = 0; } for (j=0; j<3; j++) { kiroku[i][j] = 0; } } これだけでは動かないのは理解しております。 sharedObjectと配列を使って、読み込み、書き込みする 方法を教えてくださいお願いします。

    • ベストアンサー
    • Flash

専門家に質問してみよう