ハッシュオブジェクトでマジカルバナナのデータを順番通りに連結する

ハッシュオブジェクトが効果的な状況として、自己参照してループしながらキールックアップしていくようなのものが有名です。

例えば今、マジカルバナナをした結果のデータが以下のようにあるとします。
(マジカルバナナって何?って言う世代がSASを触っていることはまだ無いと信じたい、、、)

data Q1;
length X Y $100.;
X='バナナ';Y='滑る';output;
X='冬';Y='雪';output;
X='スキー';Y='冬';output;
X='雪';Y='冷たい';output;
X='滑る';Y='スキー';output;
run;










ただし何故か、1オブザベーション目以降については、並び順が崩れてしまいました。


このデータから、





のようなデータセットを作成せよというのが今回のお仕事です。


で、それをハッシュオブジェクトで実現する場合、以下のようにかけます。

data A1;
length RESULT $100;
 if _n_=1 then do;
  declare hash hq();
   hq.definekey('X');
   hq.definedata('X','Y','FL');
   hq.definedone();
 end;
 do until(END1);
  set Q1 end=END1;
   FL=0;
   rc1=hq.add();
 end;

 do until(END2);
  set Q1 end=END2;
   rc2=hq.find();
   if rc2=0 and FL=1 then continue;
    RESULT=catx('→',X,Y);
    X=Y;
   do until(rc3^=0);
      rc3=hq.find();
      if rc3=0 then do;
       FL=1;
       hq.replace();
       RESULT=catx('→',RESULT,Y);
       X=Y;
      end;
     else output;
    end;
  end;
keep RESULT;
run;


まあ、長いですけど、大したことはしていなくて、setするデータセット自体をハッシュオブジェクトに入れておきます。
それで、Xでキーマッチングして、マッチしたら、RESULTに連結して、次はYの値をXに持ってきて、マッチしてってことです。
ポイントはハッシュオブジェクト作成の際にFLという新変数を作成していることで、こいつは、既に使用済みになった行に対してのフラグの役割を果たすわけですね。if continueのところでマッチされたデータが使用済みかを判定しているわけです。
それで、また、キーがマッチした場合はreplaceメソッドで、ハッシュオブジェクトに使用済み更新をかけています。

配列とかSQLでも同じ処理をかけるとは思いますが(ぜひ別の解法コードを教えてください)、個人的に一番しっくりくるのがハッシュオブジェクトかなぁって感じします。

ちなみにもし、バナナが先頭固定じゃない場合は、生成されたデータから文字列が最長のものを選ぶためのもう1ステップがどうしても必要になると思います。

また複数のマジカルバナナデータが混合した場合、問題はかなり複雑になります。同じワードが他のバナナで発生した場合、そっちに移ってしまう可能性があるからです。そうなると、全オブザーベーション分、作るだけ作ってから正解を選ぶ必要がありそうです。
まあ、そこまで突き詰めるような問題ではないか





4 件のコメント:

  1. なぜかPrologを思い出すなあ。

    返信削除
    返信
    1. コメント有難うございます。Prologですか。存在を知っている程度だったんですが、ちょっと調べてみたら面白そうな言語ですね。

      削除
  2. PrologとSASのmetadataマネジメントをくっつけられないか思索中です。

    返信削除
    返信
    1. それは何だか凄いことができそうですね(小学生みたいな感想ですみません)。平コード中心で、SASのプロダクトはほとんど触ったことがなくて、ちょっとイメージが追いつかないところがあるのですが、パッと検索してもそういった試みは海外の論文とかでもまだやってる人多分いなさそうなので、是非挑戦されてみてください。ユーザー総会とか発表すると、凄い反響ありそうなテーマの気がします

      削除