使用HASH对象处理多个数据集
想摄影不想学摄影
2021年05月19日 13:33
收录于文集
共44篇

一.哈希表基础概念:

  1. 是一种以   键-值(key-indexed)存储数据的结构.

  2. 可以通过键key来查找键对应的值.

  3. 如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。

  4. 在Hash表中,记录在表中的位置和其关键字之间存在着一种确定的关系。这样我们就能预先知道所查关键字在表中的位置,从而直接通过下标找到记录

  5.  哈希(Hash)函数是一个映象,即: 将关键字的集合映射到某个地址集合

  6. 使用散列表能够快速的按照关键字查找数据记录

  7. 例如,在英语字典中的关键字英文单词,和它们相关的记录包含这些单词的定义。在这种情况下,散列函数必须把按照字母顺序排列的字符串映射到为散列表的内部数组所创建的索引上。

  8. 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表

  9. 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M哈希(Hash)表,函数f(key)为哈希(Hash) 函数。

  10. 关键字为k,则其存放在f(k)的存储位置上。由此,不需比较便可直接取得所查记录。称这个对应关系f为散列函数,按这个思想建立的表为散列表。

  11. 散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位。

  12. 使用哈希表查找:(1)使用哈希函数将被查找的键转换为数组的索引。(在理想的情况下,不同的键会被转换为不同的索引值。)(2)处理哈希碰撞冲突。(有些情况下我们需要处理多个键被哈希到同一个索引值的情况。)

二.使用HASH对象处理多个数据集

  1. 使用HASH对象完成数据集之间的拼接.

  2. 优点:(1). 对数据集的排序没有要求.(2). 由于HASH对象是放入内存中的数据集,故运用HASH对象进行数据集之间的关联时效率更高.

  3. The hash object provides an efficient, convenient mechanism for quick data storage and retrieval. The hash object stores and retrieves data based on lookup keys.

  4. 使用步骤:(1).声明hash对象(2)创建hash对象的实例。(3)初始化key 和 data。

  5. 声明和实例化hash对象后,可以执行操作:(1)存取数据。(2)维护key (Maintain key summaries.)。(3)替换或删除 data。(4)比较hash对象。(5)输出在hash对象中包含的data的数据集(Output a data set that contains the data in the hash object.)。

  6. 例如:有一个large data,包含numeric lab results,这些实验室结果与唯一的病人编号patient number和体重weight关联。另外有一个small data,包含病人编号。可以将large data加载到一个hash对象,使用唯一的病人编号作为key。以weight value作为data。这样,就可以 A single pass is made over the small data set using the patient number to look up the current patient in the hash object whose weight is over a certain value and output that data to a different data set.

三. HASH对象的声明和实例化:

  1. declare hash myhash;        声明hash对象myhash = _new_ hash();    实例化一个hash对象.

  2. 上面两句代码等价于:declare hash myhash();   声明并实例化一个hash对象.

  3. 使用构造器Constructor实例化一个hash对象:创建好hash对象后,可能需要提供初始值.可以使用构造器来实例化一个hash对象并赋予初始值.

  4. 构造器语法格式一:declare hash object_name(argument_tag-1: value-1     <, ...argument_tag-n: value-n>);

  5. 构造器语法格式二:object_name = _new_ hash(argument_tag-1: value-1     <, ...argument_tag-n: value-n>);

  6. 定义Keys和Data:  使用DEFINEKEYDEFINEDATA方法。

代码块
JavaScript
自动换行
复制代码
length d $20;
length k $20;

if _N_ = 1 then do;
declare hash h();
rc = h.defineKey('k');
rc = h.defineData('d');
rc = h.defineDone();
end;
复制成功
  1. 可以有多个key和data变量,但是整个Key必须时唯一的.

  2. 可以用一个key存储多个data item.

代码块
JavaScript
自动换行
复制代码
/*each key and each data item consists of a character
value and a numeric value:*/
length d1 8;
length d2 $20;
length k1 $20;
length k2 8;
if _N_ = 1 then do;
declare hash h();
rc = h.defineKey('k1', 'k2');  /*k1是character,k2是numerical*/
rc = h.defineData('d1', 'd2');
rc = h.defineDone();
end;
复制成功

四.使用HASH对象处理多个数据集

  1. _N_  是一个内部系统变量.在DATA步 计算迭代次数.

  2. _N_ 的初始值是1, 在DATA步每次到DATA statement时自动加1。(The _N_ variable is initially set to 1 and increments by 1 each time the DATA step loops past the DATA statement.)

  3. DATA步生成和存储_N_ 变量,但不会在打印输出数据集中出现。

代码块
JavaScript
自动换行
复制代码
ata work.sales;
	input Emp_ID $ Dept $ Sales Product_ID $;
DATALINES;
ET001 TSG 100 P001
ED001 DSG 120 P001
ET001 TSG 50 P002
EC001 CSG 230 P004
EQ001 QSG 150 P003
ET001 TSG 210 P004
ET001 TSG 40 P002
ET001 TSG 150 P003
;
run;
data work.product;
	infile datalines dsd;
	length Product_ID $4 Product_Name Description $35;
	input Product_ID $ Product_Name $ Description $;
	datalines;
p001,ManufacturingIndustry Solutions,ManufacturingIndustry Solutions V2
p002,Logistics Solutions,Logistics Solutions V1
p003,Financial Service Solutions,Financial Service Solutions V3
p004,Insurance Solutions,Insurance Solutions V2
;
run;

data work.sales_description(drop = ErrorDesc)
	work.exception;
	length Product_ID $8 Product_Name Description $35;
	if _N_ =1 then 
    /*执行DATA步的第一次循环时,创建hash对象,并加载数据到hash对象.*/
		do;
		declare hash product_desc(dataset:'work.product');
		product_desc.definekey('Product_ID');
		product_desc.definedata('Product_Name','Description');
		product_desc.definedone();
        /*call missing()消除日志中部分变量没有初始化的信息.*/
		call missing (Product_ID,Product_Name,Description);
	end;
	
	set work.sales;
	rc=product_desc.find();
    /*系统调用find()在Hash对象中检索数据.*/
    /*find()可以指定sales数据集中的KEY变量,当未指定任何KEY变量的死后
    系统默认Sales数据集的KEY变量和HASH对象的KEY变量同名.*/
    /*当系统 检索到HASH对象中存在的某个KEY值和PDV中KEY变量的值相等时,则返回代码rc的取值为0,
    同时将HASH对象中对应的DATA变量的值读入PDV中.*/
	if rc=0 then 
    /*系统判断rc=0,将PDV中的数据写入到数据集work.sales_description中.*/
		output sales_description;
	else	
		do;
			ErrorDesc='No Product Description';
			output exception;
		end;
	drop rc;
run;
/*代码运行有问题:
NOTE: 变量 Product_Name 未初始化。
NOTE: 变量 Description 未初始化。
*/
/*使用 put rc=; 后
rc=160038
rc=160038
rc=160038
rc=160038
rc=160038
rc=160038
rc=160038
rc=160038
*/
复制成功