本博客将介绍IDL语法基础中的对象、哈希表的创建及相关的操作发法。哈希表、链表都可以看做对象,包含了add、reserve、Sort等方法。记录自己的学习+整理+理解 。
1. 对象
对象是数据(属性)和程序(方法)封装在一起的实体。对象的功能操作或接收到外界信息后的处理操作成为方法(来自《IDL程序设计——数据可视化分析与ENVI二次开发》)。举个栗子,例如计算计算计算圆的相关性质,可以是计算圆的直径、面积、周长……
1.1 创建对象
可以利用Obj_New()函数、ObjArr()函数来创建对象,语法如下:
Result = OBJ_NEW( [ObjectClassName [, Arg1...Argn]] )
Result = OBJARR( D1[, ..., D8] )
ObjectClassName是指IDL提供的对象名字,IDL提供的对象形如IDLxxYYYY,xx表示类的类型,YYYY表示类的名称。例如IDLgrImage表示类为图形(gr是graphics的缩写)中的图像(Image)对象;IDLgrPDF表示类为图形(gr是graphics的缩写)中的PDF对象;IDLgrView表示类为图形(gr是graphics的缩写)中的视图(view)对象。IDL中提供对象可以分为5类:
- Analysis Object Classes 分析对象类 简称:an
- File Format Object Classes 文件格式对象类 简称:ff
- Graphics Object Classes 图形对象类 简称:gr
- Network Object Classes 网络对象类 简称:net
- Miscellaneous Object Classes 其他项目类别 简称:_、db、com等
对象查看地址:帮助文档中 Routines (alphabetical) > Object Classes
例子:新建一个IDLgr
>>oImage = Obj_new('IDLGRIMAGE')
>>help,oIMAGE
OIMAGE OBJREF = <ObjHeapVar1(IDLGRIMAGE)>
IDL8.0之后版本,也可以直接吧对象当做函数使用,直接创建新的对象,格式如下:
Result = ObjClassName([Arg1...Argn])
ObjClassName表示对象的名称,例如IDLgrPDF、IDLgrImage……
>>oImage1 = Idlgrimage()
>>help,oImage1
OIMAGE1 OBJREF = <ObjHeapVar4(IDLGRIMAGE)>
注: Arg1...Argn表示参数、属性,也可以通过对象设置属性的方法设置对象属性Setproperty。反之,获取对象属性,可以利用Getproperty。
>>oImage1 = Idlgrimage(Name='Hulz') ; 新建Idlgrimage的对象oImage1,Name属性值为Hulz
>>oImage1.Getproperty,Name = Name
>>Name
Hulz
>>oImage1.Setproperty,Name = 'XMU' ; 设置对象变量oImage1,Name属性值为XMU
>>Name
XMU
注:对象创建后,可以利用Obj_Valid()进行验证,
Result = OBJ_VALID( [Arg] [, /CAST] [, COUNT=variable] [, /GET_HEAP_IDENTIFIER] )
常配合 IF (OBJ_VALID(obj)) THEN …一起使用。
1.2 调用对象
调用对象本质就是调用所包含的方法,对象的方法是有两大类组成,过程Produre和函数function。我的上一个博客中所讲的链表以及前面的博客中将的IDLffshape,也是一个对象,其中该对象的方法如博客中的2.2小结所示,有List::add、list::Count……这些方法都是针对链表list的操作方法。
在以下示例中,读取 states.shp Shapefile 中的所有实体,然后调用 DestroyEntity 方法来清理所有指针(代码来自官方示例):
PRO Ex_shapefile; 代码来自官方示例程序; 打开示例目录中的 states Shapefilemyshape=Obj_new('IDLffShape', Filepath('states.shp', $SUBDIR=['examples', 'data'])); 获取实体的数量,以便我们可以解析它们。myshape.Getproperty, N_ENTITIES=num_ent; 阅读所有实体。 Shapefile 中的实体数组从索引零 (0) 开始。FOR x=0, (num_ent-1) DO BEGIN; Read the entity x; ent = myshape.Getentity(x)ent = myshape->Getentity(x); 清理指针; myshape.Destroyentity, entmyshape->Destroyentity, entENDFOR; 关闭 Shapefile.Obj_destroy, myshape
END
下面一段为读取Shape文件存放的数据
FUNCTION Read_shape_disp,Files;COMPILE_OPT idl2; 选取shape文件Tmp = Strpos(File_basename(Files),'.shp')Shp_Files = Files(Where(Tmp > 0)); Shape文件个数N_Files = N_elements(Shp_Files)attr_values = !null ; 空矩阵,存放数据FOR index = 0L, N_Files-1 DO BEGIN;读取shp文件的信息oshp=Obj_new('IDLffShape',Shp_Files(index))IF ~Obj_valid(oshp) THEN Return,0oshp->Getproperty,n_entities=n_ent,$ ;记录个数Attribute_info=attr_info,$ ;属性信息,结构体, name为属性名ATTRIBUTE_NAMES = attr_names, $n_attributes=n_attr,$ ;属性个数Entity_type=ent_type ;记录类型;循环中,读取每条shp记录FOR i = 0, n_ent-1 DO BEGINent = oshp->Getentity(i, /ATTRIBUTES) ;第i条记录,获取数据attr_values = [attr_values, (*(ent.ATTRIBUTES)).(0)]ENDFORENDFORValue_Ave = Mean(attr_values,/Nan) ; 计算均值Return,Value_Ave
END
1.3 对象常用函数
为了更方便使用对象,官方还给出了几个对象常用函数,常见的函数有:Obj_Class()、Obj_HasMethod()、Obj_IsA()。
1.3.1 Obj_Class()
Obj_Class()函数是用来获取对象的基类或继承类的名称。
>>oshp=Obj_new('IDLffShape')
% Loaded DLM: SHAPEFILE.
>>oshp2 = obj_Class(oshp)
>>help,oshp
OSHP OBJREF = <ObjHeapVar8(IDLFFSHAPE)>
>>help,oshp2
OSHP2 STRING = 'IDLFFSHAPE'
1.3.2 Obj_HasMethod()
Obj_HasMethod()函数是用来判断对象是否具备某个方法,具备该方法则输出1,反之为0
>>oshp=Obj_new('IDLffShape')
>>print,Obj_hasmethod(oshp,'Getentity')1
>>print,Obj_hasmethod(oshp,'AAAAA');胡编的方法AAAAA0
1.3.3 Obj_IsA()
Obj_IsA()函数是用来对象是否是某个类的实例,是,则输出1,反之为0.
>>oshp=Obj_new('IDLffShape')
>>print,Obj_IsA(oSHP,'IDLffShape')1
>>print,Obj_IsA(oSHP,'IDLgrImage')0
1.4 销毁对象
利用OBJ_DESTROY过程销毁对象,语法如下:
OBJ_DESTROY, ObjRef [, Arg1, …, Argn]
若销毁所有现有的指针堆变量使用命令: OBJ_DESTROY, OBJ_VALID()。
2. 哈希表
哈希表是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。(来源于:百度百科)
注:哈希表可以视为一个官方设定的最基础的对象,从角度上,学习哈希表、链表,更容易理解它们复杂的操作方法。
>>A = Obj_new('HASH')
>>A
{
}
>>help,A
A HASH <ID=12 NELEMENTS=0>
>>B = Hash()
>>help,B
B HASH <ID=23 NELEMENTS=0>
其中,两种方法获取的哈希表是一样的,ID是系统分配的,任何变量都不一致
2.1 创建哈希表
可以利用函数Hash()创建哈希表(可以理解为创建哈希表的对象)。
语法如下:
Result = Hash( Key1, Value1, Key2, Value2, ... KEYN, Valuen, /EXTRACT, /FOLD_CASE, /NO_COPY )
Result = Hash( Keys, Values, /EXTRACT, /FOLD_CASE )
Result = Hash( Keys , /FOLD_CASE )
Result = Hash( Structure, /EXTRACT, /FOLD_CASE, /LOWERCASE)
创建一个哈希表,存放个人信息:Name、Work、Age、From,这些其实就是哈希表中的Key,其所对应的值就是Value。
>>Me = Hash('Name','胡','Work','搬砖','Age',18,'From','Jiangxi')
>>help,Me
ME HASH <ID=1 NELEMENTS=4>
>>Print,Me
Age: 18
Work: 搬砖
Name: 胡
From: Jiangxi
>>Print,Me['From'] ; 查看From关键字
Jiangxi
哈希表没有Add方法,但可以使用Hash["Key"] = Value
>>Me['Love'] = 'Wife'
>>Print,Me['Love']
Wife
2.2 访问哈希表
访问方法如下:
hash['Keys']
>> ; 该代码承接上一个代码
>>Print,Me['From']
Jiangxi
注意:此处关键字是区分大小写的,如下所示。
>>Print,Me['Name']
胡
>>Print,Me['name']
% Key does not exist: "name"
% Execution halted at: $MAIN$
2.3 哈希表操作方法
2.3.1 Hash::Count 统计
该方法是统计哈希表中元素(关键字、或有个关键字所对应的元素)的个数
Result = hash.Count( [Value] )
>>Num = Me.Count()
>>Num5
>>Print,N_elements(Me)5
2.3.2 Hash::Filter 过滤
该方法是过滤选出满足条件的哈希表中的元素,生成新的哈希表,且不改变原有的哈希表。
Result = hash.Filter( Function, Args )
; 本代码来自官方代码
FUNCTION Myfilterfunction, valueReturn, value LE 3 || Min(value MOD [2:Fix(Sqrt(value))])ENDPRO Hash_Test;Use your FUNCTION to Return only the prime numbers In HASH:var = Hash('A', 4, 'B', 5, 'C', 499, 'D', 1000)newvar = var.Filter('myfilterfunction')Print,newvar
END
输出结果为:
2.3.3 Hash::HasKey 判断关键字
该方法判断是否有一个关键字key,是则输出1,反之则为0。
Result = hash.HasKey(Keys )
>>Me = Hash('Name','胡','Work','搬砖','Age',18,'From','Jiangxi')
>>Me
{"Age": 18,"Work": "搬砖","Name": "胡","From": "Jiangxi"
}
>>Print,Me.haskey('Work')1
>>Print,Me->haskey('Work')1
>>Print,Me->haskey('A')
2.3.4 Hash::IsEmpty 是否为空
测试哈希表是否为空、存在。若为空则输出0,若非空,则输出1。
Result = hash.IsEmpty( )
>>Me = Hash('Name','胡','Work','搬砖','Age',18,'From','Jiangxi')
>>Print, Me.Isempty() ; 存在时0
>>I = Hash()
>>Print, I.Isempty() ; 空1
2.3.5 Hash::Keys 获取关键字key
该方法是用来获取哈希表中的关键字key。
Result = hash.Keys( )
>>Print, Me.Keys()
Age
Work
Name
From
2.3.6 Hash::Map 判断
该方法是用来判断各个关键字所对应的元素是否满足要求(自定义函数、lambda),满足则
Result = hash.Map( Function, Args )
输出的结果是一个哈希表,其关键字与所需处理的哈希表一样,每个关键字对应的元素只能是0或1。该方法与hash::filter方法一样,不同之处在于hash::filter是筛选满足要求的哈希表关键字(及对应元素),Hash::Map方法是判断是否满足要求,满足则关键字对应的元素为1,反之则为0。
下面是代码与2.3.2节代码一样,不同之处在于这代码使用hash::map方法。
FUNCTION Myfilterfunction, valueReturn, value LE 3 || Min(value MOD [2:Fix(Sqrt(value))])ENDPRO Hash_Test;Use your FUNCTION to Return only the prime numbers In HASH:var = Hash('A', 4, 'B', 5, 'C', 499, 'D', 1000)newvar = var.map('myfilterfunction') ; hash::map方法,判断关键字对应的元素是否满足要求Print,'newvar结果:'Print,newvarhelp,'newvar的类型:',newvar
END
结果显示输出的结果是一个哈希表,其关键字key和原哈希表一致:
2.3.7 Hash::Reduce 累积
该方法通过用户定义的函数或 Lambda 函数累积传递每个数据值,并返回单个标量结果。
Result = hash.Reduce( Function, Args, VALUE=value)
FUNCTION myreducefunction, accumvalue, valueReturn, accumvalue + valueENDPRO Hash_test;Use your FUNCTION on a Hash OF key-value PAIRS:var = Hash('Name','胡','Work','搬砖','Age','18','From','Jiangxi')newvar = var.Reduce('myreducefunction')Print, newvar
END
注:“累积”的顺序是按照key的字母排序,而不是实际的排序。
2.3.8 Hash::Remove 删除
该方式是移除Hash中的元素,并可选择返回移除的值。
Result = hash.Remove( [, Keys] [, /ALL] )
hash.Remove [, Keys] [, /ALL]
>>Me = Hash('Name','胡','Work','搬砖','Age','18','From','Jiangxi')
>>Me.Remove,['Work','Age']
>>Me
{"Name": "胡","From": "Jiangxi"
}
>>
2.3.9 Hash::ToStruct 转化为结构体
该方法是将哈希表转化为结构体。
Result=hash.ToStruct( [, MISSING=value][, /NO_COPY] [, /RECURSIVE] [, SKIPPED=variable] )
>>Me = Hash('Name','胡','Work','搬砖','Age','18','From','Jiangxi')
>>I = Me.tostruct()
>>help,I
** Structure <3d58e550>, 4 tags, length=64, data length=64, refs=1:AGE STRING '18'WORK STRING '搬砖'NAME STRING '胡'FROM STRING 'Jiangxi'
2.3.10 Hash::Values
该方法返回一个包含哈希中所有值的 LIST。只要没有从哈希中添加或删除任何项目,hash.keys 和 hash.Values() 中的键/值对的顺序就保证保持相同。
Result = hash.Values( )
>>Me = Hash('Name','胡','Work','搬砖','Age','18','From','Jiangxi')
>>list = Me.Values()
>>help,list
LIST LIST <ID=34 NELEMENTS=4>
>>print,list
18
搬砖
胡
Jiangxi
>>
2.3.11 Hash::Where
该方法返回包含某个 value.hash 的所有键的 list。
Result = hash.Where( Value [, COMPLEMENT=variable] [, COUNT=variable] [, NCOMPLEMENT=variable] )
2.4 销毁哈希表
可以使用Obj_destroy,Hash 来销毁哈希表
>>Me = Hash('Name','胡','Work','搬砖','Age','18','From','Jiangxi')
>>ME
{"Age": "18","Work": "搬砖","Name": "胡","From": "Jiangxi"
}
>>Obj_destroy,Me
>>Me
<ObjHeapVar1>