ユニークなIDとか作れって言われたらの話

多分需要ないし、方法に工夫もないけど、与えらえた文字列から指定の長さで
ユニークなIDを作成するマクロです。

すでに発行済のIDが入ったデータセットを指定することで
過去に発行したものとも重複しない作成が可能です。

使用可能文字の数と、作成IDの長さの設定によって、生成できるIDの限界数が
決まります。
例えば100万の生成限界なのに90万のIDを発行したりすると実行効率遅いです。
生成限界はできるだけ余裕を持たせてください。

アルゴリズムは単純ですが
生成限界がぶっとんだ値であれば、何十万発行しようが結構速いと思います。

すでに存在するデータセットに付与して作りたい場合は
マクロをちょっと書き換えてsetをいれて、do untilのループをとっちゃえばいいです。


%macro unique_make(outds=,obs=,idlength=,seed=,moji=,ban=);
/*--------------------------------------------------------
outds=作成されるデータセット
obs =作成するオブザベーション数
idlength=作成される文字列の長さ
seed =作成のための乱数シード
moji =使用する文字列(半角英数字)
ban  =データセット指定(ここにあるidは作成されない)
----------------------------------------------------------*/
data &outds(keep = id);
length id $&idlength..;
if _N_ = 1 then do;
declare hash h1
%if %length(&ban) =0 %then %do;();%end;
%else %do;(dataset:"&ban");%end;
h1.definekey('id');
h1.definedone();
end;
x="&moji";
n=length(x);
kumi=n**&idlength;

put 'NOTE:与えられた文字の数は ' n;

put 'NOTE:生成限界は ' kumi;

call streaminit(&seed);

do until(obs=&obs);
do until(okfl=1);
do i = 1 to &idlength;
r=int(rand('uniform') * n +1);
id = cats(id , char(x,r));
if i = 5 then do;
if h1.check() ne 0 then do;
okfl=1;
h1.add();
output;
obs+1;
end;
else id='';
end;
end;
end;
end;
run;
%mend;

以下実行例です。


/*英数字で5桁のIDを10000発行*/

%unique_make(outds=A1
 ,obs=10000
 ,idlength=5
 ,seed=2345
 ,moji=abcdefghijklmnopqrstuvwxyz0123456789
);

/*先に発行したA1とかぶらないようにさらに10000発行*/

%unique_make(outds=A2
 ,obs=10000
 ,idlength=5
 ,seed=6789/*シード変えた方がよい*/
 ,moji=abcdefghijklmnopqrstuvwxyz0123456789
 ,ban=A1
);

0 件のコメント:

コメントを投稿