哈希表.docx

上传人:b****5 文档编号:7758283 上传时间:2023-01-26 格式:DOCX 页数:7 大小:20.28KB
下载 相关 举报
哈希表.docx_第1页
第1页 / 共7页
哈希表.docx_第2页
第2页 / 共7页
哈希表.docx_第3页
第3页 / 共7页
哈希表.docx_第4页
第4页 / 共7页
哈希表.docx_第5页
第5页 / 共7页
点击查看更多>>
下载资源
资源描述

哈希表.docx

《哈希表.docx》由会员分享,可在线阅读,更多相关《哈希表.docx(7页珍藏版)》请在冰豆网上搜索。

哈希表.docx

哈希表

以下是本人对《TheDATAstepinSAS®9:

WhatsNew?

》一文所作的翻译草稿,可能对大家进一步学习sas有帮助。

因水平有限,不可避免的出现如概念翻译不正确或不准确,语句不地道,逻辑有误,或者误解原文作者的意图等等不足,希望看过的朋友指出,以便进一步修改。

原文来自SASSUGIproceedings:

原作者JasonSecosky,SAS,Cary,NC.

建连:

SAS9.0数据步的新功能

(二)

组件对象接口

为了整和新数据结构到DATA步中,添加了DECLARE语句和对象点语法。

这样可以创建一个类实例(也叫对象),然后用点语法调用对象方法,如OBJ.METHOD(),提供的初始类是一个哈希表。

哈希表可以将数据存储到一个可扩展的表中,这样具有快速查询的功能它与数据步数组类似,索引在数组中用来存储和提取数据。

数组用标记,而哈希表能用字符、数字或字符和数字的组合做标记。

与数组不同,创建哈希表时,存储值的个数的不被指定,只要要内存容许,可以保存足够多的数值。

当添加数据到哈希表中,索引通常称为关键词,常常用做复制数据到表中某个位置。

当从一个哈希表中提取数据时,如果数据表中有带关键词的数据,可根据这个关键词进行快速非线性搜索,返回带关键词的数据。

关键词和数据是个一个字符矢量,数字矢量或字符数字矢量。

如一个字符社会安全号码(SSN)可以是一个关键词去定位一个人的姓名、地址和其他信息。

当添加数据时,一个SSN和个人信息都添加都哈希表中,当提取数据时,根据给出的SSN就可以返回根据以此SSN为关键词存储的数据。

这种类型的操作在数据步中早有了,不过用哈希表来做速度更快。

带关键词的set语句根据给定的关键词将一排数据载入到PDV中,用哈希表的话,不需要搜索数据集的索引,查询在内存中执行而不是在硬盘上。

带by的Merge也可以用,不过需要已排序或索引的输入数据集。

装载到哈希表中的数据不需要预先排好序,格式可以用于大的未排序数据集中查询表方法。

哈希表比用格式更快,内存占用更少,能根据一个关键词存储多个数据项。

用大量数据时,格式方法占用大量的硬盘空间,而哈希表则不需要。

下节将讲述数据步中哈希表的用法。

用哈希表做关键词查询。

哈希表的常用用法是用关键词/数据装载,然后通过带关键词的哈希表查询数据集。

下面的例子说明怎么装载一个主数据集,怎么用一个执行数据集来查询,主数据集有变量key和val,执行数据集有变量key。

代码:

data merged;

        length key $13;

        length val 8;

        if_N_=1thendo;

          declareHashht(dataset:

“master”);

          ht.defineKey(“key”);

          ht.defineData(“val”);

          ht.defineDone();

        end;

       

       /*Loadkeyandqueryhashtable*/

      settrans;

        if ht.find()=0;

run;

在这个例子中,申明并初始化了一个新的哈希表ht。

构造器被指令装载名为master的数据集到此哈希表中,命名参数dataset用来表明需要被装载的数据集。

命名参数允许以任何顺序的多个参数传递,帮助记录出现的参数。

与临时数组类似,保留对象放弃所有输出数据集。

在数据装载到一个数据集之前,哈希表的关键词和数据变量必须被指定方法defineKey,defineData执行这步操作。

这里指定了一个关键词变量key和一个数据变量val。

多个关键词和数据变量可以用defineKey,defineData指定更多的变量名。

当关键词和数据变量定义完成后,调用defineDone方法,这将使数据集装载到哈希表中,请注意哈希表的大小没有指定,哈希表将加载的数据量在内存中增大。

在程序查询阶段,用set语句装载执行数据集中的值,find方法用关键词变量的当前值在哈希表中执行查询。

如果匹配就移动数据变量的值。

如果成功find方法返回值为0,失败则为非零。

关键词查询执行

为了测试执行速度,用format,带key的set,带by的merge做哈希表同一个搜索操作,结果见下表,这个例子中,执行同样的查询,哈希表比其他的方法少用1.9到5.9倍的时间。

用format,花在format和format查询都比用哈希表查询长。

带key的set方法要花时间建立索引,并且硬盘查询不内存中查询慢。

带by的merge速度不错,但输入数据集必须排序或索引,对于查询无序数据,内存允许的话,哈希表是一个不错的选择。

执行查找实际时间

SETwithKEY=108.14s

BuildIndex11.33s

Search96.81s

FormatandPUT()89.03s

BuildFormat67.32s

Search21.71s

MERGEwithBY35.78s

SortDataSets31.60s

Search4.18s

HashTable18.35s

LoadandSearch18.35s

每次测试,表中第一行是总时间,缩进行分别是每步操作的所用的时间,都是运行在Windows系统SAS9.1记录的时间。

给出了三个执行最快的一个。

测试在CPU为1.6G,内存为1G,奔四机器上,操作系统为XPPROFESSIONAL。

数据集master有500万条key/data对数据集trans中有500万搜索关键词。

关键词是一个13个字符值和一个8字节数字值。

半数的搜索关键词存在于master数据集中。

添加数据

哈希表中的数据可以从数据集以外的数据源中加载,如果没有数据集被传递到哈希表构造器中,就会初始一个空的哈希表,add方法可以把数据添加到哈希表中。

下面的例子是从输入文件装载数据到哈希表中,在数据装载后执行查找。

代码:

 data_null_;

     length first last title  $16;

     length borndied 8;

     if_N_ = 1thendo;

       declare Hash ht();

       ht.defineKey(“first”,“last”);

       ht.defineData(“born”,”died”,”title”);

       ht.defineDone();

     end;

     infiledatalineseof=search;

     input first lastborndiedtitle &$16.;

    ht.add();

    /*

      ht.add(0 isthesameas:

      ht.add(key:

first,key:

last,data:

born,data:

died,data:

title);

*/

   return;

   search:

    rc=ht.find(key:

”John”,key:

“Keats”);

    if rc=0 then

      put“FoundJohnKeats”title$QUOTE.;

   datalines;

   WilliamBlake  1757 1827 Sping

   JohnKeats   1795 1821 ToAutumn

   MaryShelley  1797 1851 Frankenstein

   ;

Output

FoundJohnKeats“ToAutumn”

如果在没有参数情况下调用add方法,将会复制当前的关键词和数据变量到哈希表中。

如果给出了参数,那些值就会在哈希表中用到参数的次序必须和定义的关键词和数据变量的次序一致。

比喻,如果参数born和died在用add方法时被调换,那么在取数据时,出生年的数据放入died中,死亡年的数据放入born中。

这个例子同样示例了一个关键词的多个值或一个数据的多个值。

注意数据项是混合类型的。

哈希表输出和排序

转载好一个哈希表后,哈希表中的数据就可以用output方法不断地输出数据到数据集中。

这些数据集可以被其中proc步使用,也可以用进一步的DATA步装载到哈希表中。

除非建立哈希表的时候通过命名参数ordered传递ascending或decending传值,用输出方法得到的行输出没有排序。

当用了参数ordered,数据项根据关键词排序。

下面给出了个例子,怎么将Patient和diacharger数据装入一个哈希表中,并从哈希表中输出到按patient排序的数据集sort_ids中。

代码:

  data _null_;

     lengthpatient_id $16discharge 8;

     if_N_=1thendo;

       declare Hashht(ordered:

”yes”);

       ht.defineKey(“patient_id”);

       ht.defineData(“patient_id”,“discharge”);

       ht.defineDone();

     end;

infiledatalineseof=output;

    inputpatient_iddischarge:

DATE9.;

    ht.add();

    return;

  output:

   ht.output(dataset:

“sorted_ids”);

datalines;

Smith-412315MAR2004

Hagen-283423APR2004

Smith-243715JAN2004

Flinn-294012FEB2004

;

data_null_;

  setsorted_ids;

  putpatient_iddischarge:

DATA9.;

Output:

  Flinn-294012FEB2004

  Hagen-283423APR2004

Smith-243715JAN2004

Smith-412315MAR2004

注意可以用output方法输出数据变量,对应的数值,而不能输出关键词对应的数值。

为了能保留关键词的数值。

关键词必须加入哈希表的数据部分。

上面的例子用Patient_id既可以作关键词变量又做数据变量。

如果patient_id仅做为关键词变量,那么patient_id对应的值不会出现在输出数据集中。

哈希表重复

在哈希表组件中,还有一个哈希表重复组件。

hashiterator能顺序地获得哈希表中的数据元素。

当hashiterator建立时,hashiterator能进行全部重复。

下面的例子装载patient_id和discharge数据到哈希表中,并用一个hashiterator输出各项到log中。

data_null_;

lengthpatient_id$16discharge8;

if_N_=1thendo;

declareHashht(ordered:

”yes”);

ht.defineKey(“patient_id”);

ht.defineData(“patient_id”,“discharge”);

ht.defineDone();

end;

infiledatalineseof=process;

inputpatient_iddischarge:

DATE9.;

ht.add();

return;

process:

declareHIteriter(‘ht’);

rc=iter.first();

dowhile(rc=0);

putpatient_iddischarge:

DATE9.;

rc=iter.next();

end;

data_null_;

setsorted_ids;

putpatient_iddischarge:

DATA9.;

Output:

Flinn-294012FEB2004

Hagen-283423APR2004

Smith-243715JAN2004

Smith-412315MAR2004

除了数据总输出到log中而不是数据集中。

这个程序与演示output方法的例子有点像。

语句declarehiter被用于建立名为iter的hashiterator。

当iterator建立后,哈希表名迭代过头,“ht”被传到iteror构造器中。

interator一经建立,有四个方法FIRST,LAST,NEXT和PREV可被用来从哈希表中提取数据。

上面例子中,FIRST方法被用来得到哈希表中第一项。

NEXT方法用来得到哈希表中下一项。

所有iterator方法在该项找到时返回0,找不到就返回1。

这个例子中,当NEXT方法返回1时,DOWHILE循环停止,也就意味着再没有元素从哈希表中返回。

因为在output方法例子中,命名参数ordered为hashiterator赋值过头导致iterator按哈希表关键词返回排序的数据。

如果ordered参数没有被设置,返回的数据就不能确定是否排序。

哈希表INTERNALS

哈希表是一个bucket数组,当以一个关键词增加数据或搜索数据时,关键词被传递到能返回插入数据的或找到一个bucket号码的哈希函数。

当bucket中有多个keyshash时,key/data对存在AVL树中。

如果放入哈希表中key/data对的数组个数大于bucket的个数时。

因为AVL树将包含一些项目,所以执行速度减慢。

搜索一个AVL树比搜索一个全部项放入哈希表bucket要慢。

与此相反,如果放入哈希表中的key/data对的数目小于bucket,那么许多bucket就会是空的。

没有用的bucket会浪费内存,然而大多情况下,浪费的总内存是很小的,如缺省的bucket数为256个,每个bucket为8字节,所以就算只有到一半的bucket,也只有1024字节被浪费。

作为一个执行调整参数,被哈希表用到的bucket个数能改变,可以用哈希表构造器hashexp命名参数改变bucket数组。

hashexp值为在项目apoweroftwo的哈希表指示bucket数目。

declareHashht(hashexp:

6);

将会为哈希表初始化26即64个bucket。

Hashexp最大值为16。

一般来说,百万条的key/data对28或29bucket的哈希表中丝毫不会让速度打折扣。

一个哈希表能不断增大,直到内存耗尽为止。

但是调整数组大的key/data对的bucket个数可能会提高add和find方法的执行速度。

_NEW_OPERATORANDDELETEMETHOD_NEW_操作符和DELETE方法

随着可以用DECLARE语法可以创建一个对象,_NEW_操作符可以用_NEW_在类名和任何构造器参数前面。

为释放一个存在的对象可以调用对象的delete方法。

每个对象都有delete方法,用这个方法也不需要参数。

下面的例子用_NEW_操作符建立了一个哈希表。

一个新的哈希表将被建立和删除。

注意DCL是DECLARE语句的简写形式。

代码:

 Data_null_;

     length key1data1$8;

     length key2data28;

     dclHashht;

     ht= _new_Hash();

     ht.defineKey(“key1”,“key2”);

     ht.defineData(“data1”,“data2”);

     ht.defineDone();

/*DATAstepprocessing*/

 ht.delete();

run;

文件

对象点语法和哈希表在SAS9.0数据步中是测试用,在SAS9.1则为正式的产品。

除了上面已经讲到的方法,文档中还讲到了本文中没有提到的remove和replace方法和哈希表的num_items属性。

文档中也描叙了哈希表iterator的LAST和PREV方法。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1