配列No.08973
いちもんじ さん 19/04/18 17:41
 
タブ区切りされたデータファイルをクリップボードに読み込み、下記のマクロで配列
に割り当てることをしています。

データ群の横、縦に長くなればなるほど、下記のマクロ(サブルーチン)を終えるの
に時間を要する時間、当然、長くなります。

この時間を短くする方法が無いかと思案中、模索中です。

秀丸エディタ自体が大量の行数のファイルを扱えるので、配列に関係するあたりも
「大量」なデータが扱えやすくなると良いのに...と思います。

例えば、統計処理ソフト「R」などは、データファイルを読み込むだけで、配列に自
動的に割り当てられるようですが、そのような機能(関数)があれば、スピーディに
処理できるのに....と思うこの頃です。

まぁ、エディタにそれを求めるのはお門違いなのかも知れませんけど...

---------------------------------------------------------------
SPLIT_DATA:
    ##l = strlen( $$1 );
    ##p = strlen( $$2 );
    ##a = ##3;

    ##b = 0;
    while( 1 ){
        if( !##l ) break;
        ##s = strstr( $$1, $$2 );
        if( ##s == -1 ){
            $SPLIT_DATA[##a][##b] = $$1;
            ##b = ##b + 1;
            break;
        }
        $SPLIT_DATA[##a][##b] = leftstr( $$1, ##s );
        ##l = ##l - ##s - ##p;
        $$1 = rightstr( $$1, ##l );
        ##b = ##b + 1;
    }

return ##b;

[ ]
RE:08973 配列No.08974
IKKI さん 19/04/18 20:02
 
いちもんじさん、こんばんは。ユーザーの IKKI です。

秀丸マクロの変数は数が多くなるほどアクセスに時間がかかります。私が以前ベンチ
マークした結果がここにあります。
http://mobitan.org/hm/memo/130428/

現状で大量のデータを扱う方法としては、
 ・秀丸の編集画面にデータを展開する
 ・macrodll のハッシュを使う
 ・COM 経由で MS Access や SQLite などのデータベースに接続する
といった方法が考えられます。
根本的には、秀丸マクロはフロントエンドの処理に特化し、大量のデータ処理は専用
のバックエンドで行うように設計するのが良いと思います。

以上、ご参考になれば幸いです。

[ ]
RE:08974 配列No.08975
いちもんじ さん 19/04/18 20:29
 
>現状で大量のデータを扱う方法としては、
> ・秀丸の編集画面にデータを展開する
> ・macrodll のハッシュを使う
> ・COM 経由で MS Access や SQLite などのデータベースに接続する
>といった方法が考えられます。


 簡単で良いので、マクロの例(上記の方法の使い方)をご教示いただけないでしょ
うか?

 私がやりたいのは、
  横に400個、縦に1000行で並ぶ、タブ区切りのデータ
 を
  $data[0][0]〜$data[399][999]
 に当てはめる...です。

[ ]
RE:08975 配列No.08976
IKKI さん 19/04/18 21:11
 
少し言葉足らずだったかもしれません。私のコメントの要旨は

 ・現状、秀丸マクロで多数の変数を扱うことは非現実的である
 ・「変数にデータを当てはめる」という考えを捨てるべき

ということでした。
いちもんじさんが最終的に何を実現したいかによって有効な解決策は異なると思いま
す。

[ ]
RE:08976 配列No.08977
いちもんじ さん 19/04/18 21:28
 
> ・現状、秀丸マクロで多数の変数を扱うことは非現実的である
> ・「変数にデータを当てはめる」という考えを捨てるべき
>

 おっしゃる通りかと思います。

 性格なのか、限界を探るというか、無理は承知というか。
 秀丸マクロで、一体、どれほどのことができるのかに、(ある意味、意地悪く)挑
戦してみるということもありまして...


 今更、新しいプログラム言語を学習する年齢でもなく、「マクロ」ならどうにか使
えるレベルですので、マクロに頼りたくなってしまうのです。

[ ]
RE:08973 配列No.08978
いちもんじ さん 19/04/18 21:37
 
やりたいことは、下記のマクロによる処理のスピードを早くすることです。

disabledrawやファイルを開くときに"/h "オプションをつけても、思ったほどスピー
ドは上がらなくて...

クリップボードから1行づつ読み取るgetclipboardを使うから、遅いのでしょうか?
(でも、これしか方法が無いようですし...)



>---------------------------------------------------------------
>SPLIT_DATA:
>    ##l = strlen( $$1 );
>    ##p = strlen( $$2 );
>    ##a = ##3;
>
>    ##b = 0;
>    while( 1 ){
>        if( !##l ) break;
>        ##s = strstr( $$1, $$2 );
>        if( ##s == -1 ){
>            $SPLIT_DATA[##a][##b] = $$1;
>            ##b = ##b + 1;
>            break;
>        }
>        $SPLIT_DATA[##a][##b] = leftstr( $$1, ##s );
>        ##l = ##l - ##s - ##p;
>        $$1 = rightstr( $$1, ##l );
>        ##b = ##b + 1;
>    }
>
>return ##b;

[ ]
RE:08978 配列No.08980
秀丸担当 さん 19/04/19 09:08
 

マクロで配列を使う場合の注意点についてはIKKIさんの言われる通りで、現状では配
列を使う限りは難しいところがあります。
効率が悪いところもあるので、改善を検討したいと思います。

現状でなんとかする方法の1つとして、COMオブジェクトのScripting.Dictionaryを
使うと、外部のソフトを入れずに標準のままでできるので、いいかもしれません。
配列というより文字列に対応する文字列という感じですが、例えば以下のような感じ
に使えるようです。

#objDic=createobject("Scripting.Dictionary");
member #objDic, "Add", "a1", "a1の値";
member #objDic, "Add", "a2", "a2の値";
message member(#objDic,"Item","a1");
message member(#objDic,"Item","a2");
endmacro;


今回の例に当てはめると、以下のような感じになるのではないかと思います。

#objDic = createobject("Scripting.Dictionary");
beginclipboardread;
#i = 0;
while( 1 ) {
    $a = getclipboard;
    if( $a == "" ) break;
    call SPLIT_DATA $a,"\t",#i;
    #i = #i + 1;
}

//配列を使う場合
//message "[1][1]の値:\n" + $SPLIT_DATA[1][1];

//Scripting.Dictionaryを使う場合
message "[1][1]の値:\n" + member(#objDic,"Item","SPLIT_DATA-1-1");

endmacro;

SPLIT_DATA:
    ##l = strlen( $$1 );
    ##p = strlen( $$2 );
    ##a = ##3;

    ##b = 0;
    while( 1 ){
        if( !##l ) break;
        ##s = strstr( $$1, $$2 );
        if( ##s == -1 ){
            $SPLIT_DATA[##a][##b] = $$1;
            ##b = ##b + 1;
            break;
        }
       
        //配列を使う場合
        //$SPLIT_DATA[##a][##b] = leftstr( $$1, ##s );
       
        //Scripting.Dictionaryを使う場合
        member #objDic, "Add", "SPLIT_DATA-"+str(##a)+"-"+str(##b), leftstr
( $$1, ##s );
       
        ##l = ##l - ##s - ##p;
        $$1 = rightstr( $$1, ##l );
        ##b = ##b + 1;
    }

return ##b;

[ ]
RE:08980 配列No.08981
いちもんじ さん 19/04/19 10:03
 
>
>マクロで配列を使う場合の注意点についてはIKKIさんの言われる通りで、現状では
>配列を使う限りは難しいところがあります。
>効率が悪いところもあるので、改善を検討したいと思います。
>

 パソコンは日々、処理速度が上がっています。眼を見張るほどです。
 (「あっという間に」とまでは行かなくてもですが)改善を検討されるとのこと、
ありがとうございます。

 また、マクロのサンプルの方も参考にさせていただきます。
 こちらもありがとうございました。

[ ]
RE:08980 配列No.08982
いちもんじ さん 19/04/19 20:36
 
>マクロで配列を使う場合の注意点についてはIKKIさんの言われる通りで、現状では
>配列を使う限りは難しいところがあります。
>効率が悪いところもあるので、改善を検討したいと思います。

身勝手な要望です。
引数で区切り文字を与えたら、列数と行数が自動的にされて配列に
個々の値(数字、文字列)が割り当てられている
...といいなぁ。
という感じです。

[ ]
RE:08982 配列No.08984
秀丸担当 さん 19/04/22 15:27
 

JavaScriptとかだとsplitという関数があるようで、そういう方法もあったらいいと
思います。
やるとしたら、現状の秀丸マクロは、配列としてまとめて受け取ったり格納したりと
いう仕組みが無いので、そのあたりからいじる必要があったりするのですが、できた
らいいということでネタとして参考にさせていただきます。

[ ]
RE:08984 配列No.08985
秀丸担当 さん 19/04/24 10:56
 

V8.89β4で、修正してみています。
マクロはそのままでも多少は改善しています。
split関数も追加していて、これにするとだいぶ良くなると思います。
今回の例の場合、例えば以下のようにして使います。

beginclipboardread;
#i = 0;
while( 1 ) {
    $a = getclipboard;
    if( $a == "" ) break;
   
    //call SPLIT_DATA $a,"\t",#i;
    #c = split($SPLIT_DATA[#i],$a,"\t");
   
    #i = #i + 1;
}

[ ]
RE:08985 配列No.08986
いちもんじ さん 19/04/24 18:37
 
>V8.89β4で、修正してみています。
>マクロはそのままでも多少は改善しています。
>split関数も追加していて、これにするとだいぶ良くなると思います。

 今は、試す時間が無いですが、なんだか良さそうな予感がします。

[ ]
RE:08986 配列No.08988
いちもんじ さん 19/04/27 15:26
 
> 今は、試す時間が無いですが、なんだか良さそうな予感がします。

試してみました。
これ、配列は1次元ですよね?
2次元配列にするには、どうすれば良いのでしょうか?

[ ]
RE:08988 配列No.08992
いちもんじ さん 19/04/29 07:13
 
>> 今は、試す時間が無いですが、なんだか良さそうな予感がします。
>
>試してみました。
>これ、配列は1次元ですよね?
>2次元配列にするには、どうすれば良いのでしょうか?

勘違いしてました。
複数行を一回でクリップボードに入れたものが二次元配列になるのかと。
マクロの方は、一行づつ取り出し配列することを繰り返して二次元配列になりました。

getclipboard、あるいはgetcliphistで複数行を指定して取り出せるようになれば、
「一行づつ取り出して」を繰り返す時間を短縮できる気がします。

[ ]
RE:08992 配列No.08993
秀丸担当 さん 19/05/07 11:09
 

自動的な二次元もあったらあったでいいと思いますが、他の言語でそこまでしている
のは見かけないのと、従来のサブルーチンで400秒くらいだったのがsplit関数で0.4
秒くらいになったので、行単位でも実用できそうと思いますがどうでしょうか。
試したのは400区切り×100行の場合で、1000行だと従来では測定困難でした。
ただsplit関数を使っても、桁数(タブ区切り数)が少なくて行数が多い場合は効果
は薄れるかもしれないです。

[ ]
RE:08993 配列No.08994
いちもんじ さん 19/05/08 15:43
 
>自動的な二次元もあったらあったでいいと思いますが、他の言語でそこまでしてい
>るのは見かけないのと、従来のサブルーチンで400秒くらいだったのがsplit関数で0.
>4秒くらいになったので、行単位でも実用できそうと思いますがどうでしょうか。

行数の多いファイルを一気処理しようとすると、時間がかかってしまうので、
ファイルを分割して処理することにしました。
(この方法のほうがかえって短時間で処理できたという結果に)

 ファイル分割→配列処理→ファイル結合

でも実害はなく、split関数の使用で個人的には問題はありません。
いろいろとご検討いただきありがとうございました。

[ ]