2018年10月9日火曜日

「=:」を使った前方一致による比較と落とし穴





文字列の比較で使える「=:」を紹介します。
落とし穴もあるので、それも含めて紹介していきます。



簡単な例


Sample data
data TEST;
input X:$3.;
cards;
ab
abc
cab
;




data OUT1;
    set TEST;
    if X =: "ab" then FLG1=1;
run;



変数Xが "ab" で始まる値かどうか、という比較を行っています。


詳しく説明すると、「=:」の両辺に指定した変数または文字列のうち、LENGTHが大きい方は、LENGTHが小さい方の長さに切り捨てて比較を行ないます。


ここでいうLENGTHとは以下を指します。
 文字列の場合 

文字列の長さ」
 変数の場合

 固定長の文字変数の場合
「文字列と末尾の空白を含む長さ(つまり変数に定義した長さ)」



上の例では、「X =: "ab"」で、
・左辺に指定した変数Xに定義されたlengthは「3」
・右辺に指定した "ab" は2バイトなのでlengthは「2」

この2つのlengthで小さいのは「2」なので、左辺の変数値を2バイトに切り捨てると以下の通り。

ab → ab
abc → ab
cab → ca

この切り捨てた値と右辺の "ab" がイコールか否か、という判定を行います。






注意が必要な例



data OUT2;
    set TEST;
    if X =: "abcd" then FLG1=1;
run;



「X =: "abcd"」で
・左辺の変数Xに定義されたlengthは「3」、
・右辺の "abcd" は4バイトなのでlengthは「4」、

lengthが小さいのは「3」なので、右辺の文字 "abcd" を3バイトで切り捨てると "abc" となります。


この "abc" が変数Xとイコールか否か、という判定を行います。
この切り捨てルールを知らないと、一見「変数Xが "abcd" で始まる値かどうか」と思ってしまいがちですが、間違いです!





今回の例のデータでもし「変数Xが "abcd" で始まる値かどうか」を判定したいなら、以下のように他の方法を使ったほうが安全です。

data OUT3;
    set TEST;
    if index( X, "abcd" )=1 then FLG1=1;    * 方法1 ;
    if find( X, "abcd" )=1 then FLG2=1;       * 方法2 ;
run;




0 件のコメント:

コメントを投稿