本博客将介绍IDL语法基础中的对象、哈希表的创建及相关的操作发法。哈希表、链表都可以看做对象,包含了add、reserve、Sort等方法。记录自己的学习+整理+理解 。
对象是数据(属性)和程序(方法)封装在一起的实体。对象的功能操作或接收到外界信息后的处理操作成为方法(来自《IDL程序设计——数据可视化分析与ENVI二次开发》)。举个栗子,例如计算计算计算圆的相关性质,可以是计算圆的直径、面积、周长……
可以利用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类:
对象查看地址:帮助文档中 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 …一起使用。
调用对象本质就是调用所包含的方法,对象的方法是有两大类组成,过程Produre和函数function。我的上一个博客中所讲的链表以及前面的博客中将的IDLffshape,也是一个对象,其中该对象的方法如博客中的2.2小结所示,有List::add、list::Count……这些方法都是针对链表list的操作方法。
在以下示例中,读取 states.shp Shapefile 中的所有实体,然后调用 DestroyEntity 方法来清理所有指针(代码来自官方示例):
-
- PRO Ex_shapefile
- ; 代码来自官方示例程序
- ; 打开示例目录中的 states Shapefile
- myshape=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, ent
- myshape->Destroyentity, ent
- ENDFOR
- ; 关闭 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,0
- oshp->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 BEGIN
- ent = oshp->Getentity(i, /ATTRIBUTES) ;第i条记录,获取数据
- attr_values = [attr_values, (*(ent.ATTRIBUTES)).(0)]
- ENDFOR
- ENDFOR
- Value_Ave = Mean(attr_values,/Nan) ; 计算均值
- Return,Value_Ave
- END
为了更方便使用对象,官方还给出了几个对象常用函数,常见的函数有:Obj_Class()、Obj_HasMethod()、Obj_IsA()。
Obj_Class()函数是用来获取对象的基类或继承类的名称。
- >>oshp=Obj_new('IDLffShape')
- % Loaded DLM: SHAPEFILE.
- >>oshp2 = obj_Class(oshp)
- >>help,oshp
- OSHP OBJREF = <ObjHeapVar8(IDLFFSHAPE)>
- >>help,oshp2
- OSHP2 STRING = 'IDLFFSHAPE'
Obj_HasMethod()函数是用来判断对象是否具备某个方法,具备该方法则输出1,反之为0
- >>oshp=Obj_new('IDLffShape')
- >>print,Obj_hasmethod(oshp,'Getentity')
- 1
- >>print,Obj_hasmethod(oshp,'AAAAA');胡编的方法AAAAA
- 0
Obj_IsA()函数是用来对象是否是某个类的实例,是,则输出1,反之为0.
- >>oshp=Obj_new('IDLffShape')
- >>print,Obj_IsA(oSHP,'IDLffShape')
- 1
- >>print,Obj_IsA(oSHP,'IDLgrImage')
- 0
利用OBJ_DESTROY过程销毁对象,语法如下:
OBJ_DESTROY, ObjRef [, Arg1, …, Argn]
若销毁所有现有的指针堆变量使用命令: OBJ_DESTROY, OBJ_VALID()。
哈希表是根据关键码值(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是系统分配的,任何变量都不一致
可以利用函数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
访问方法如下:
hash['Keys']
- >> ; 该代码承接上一个代码
- >>Print,Me['From']
- Jiangxi
注意:此处关键字是区分大小写的,如下所示。
- >>Print,Me['Name']
- 胡
- >>Print,Me['name']
- % Key does not exist: "name"
- % Execution halted at: $MAIN$
该方法是统计哈希表中元素(关键字、或有个关键字所对应的元素)的个数
Result = hash.Count( [Value] )
- >>Num = Me.Count()
- >>Num
- 5
- >>Print,N_elements(Me)
- 5
该方法是过滤选出满足条件的哈希表中的元素,生成新的哈希表,且不改变原有的哈希表。
Result = hash.Filter( Function, Args )
- ; 本代码来自官方代码
- FUNCTION Myfilterfunction, value
-
- Return, value LE 3 || Min(value MOD [2:Fix(Sqrt(value))])
-
- END
-
- PRO 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
输出结果为:

该方法判断是否有一个关键字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')
测试哈希表是否为空、存在。若为空则输出0,若非空,则输出1。
Result = hash.IsEmpty( )
- >>Me = Hash('Name','胡','Work','搬砖','Age',18,'From','Jiangxi')
- >>Print, Me.Isempty() ; 存在时
- 0
- >>I = Hash()
- >>Print, I.Isempty() ; 空
- 1
该方法是用来获取哈希表中的关键字key。
Result = hash.Keys( )
- >>Print, Me.Keys()
- Age
- Work
- Name
- From
该方法是用来判断各个关键字所对应的元素是否满足要求(自定义函数、lambda),满足则
Result = hash.Map( Function, Args )
输出的结果是一个哈希表,其关键字与所需处理的哈希表一样,每个关键字对应的元素只能是0或1。该方法与hash::filter方法一样,不同之处在于hash::filter是筛选满足要求的哈希表关键字(及对应元素),Hash::Map方法是判断是否满足要求,满足则关键字对应的元素为1,反之则为0。
下面是代码与2.3.2节代码一样,不同之处在于这代码使用hash::map方法。
- FUNCTION Myfilterfunction, value
-
- Return, value LE 3 || Min(value MOD [2:Fix(Sqrt(value))])
-
- END
-
- PRO 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,newvar
- help,'newvar的类型:',newvar
- END
结果显示输出的结果是一个哈希表,其关键字key和原哈希表一致:

该方法通过用户定义的函数或 Lambda 函数累积传递每个数据值,并返回单个标量结果。
Result = hash.Reduce( Function, Args, VALUE=value)
- FUNCTION myreducefunction, accumvalue, value
-
- Return, accumvalue + value
-
- END
-
- PRO 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的字母排序,而不是实际的排序。
该方式是移除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"
- }
- >>
该方法是将哈希表转化为结构体。
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'
该方法返回一个包含哈希中所有值的 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
- >>
该方法返回包含某个 value.hash 的所有键的 list。
Result = hash.Where( Value [, COMPLEMENT=variable] [, COUNT=variable] [, NCOMPLEMENT=variable] )
可以使用Obj_destroy,Hash 来销毁哈希表
- >>Me = Hash('Name','胡','Work','搬砖','Age','18','From','Jiangxi')
- >>ME
- {
- "Age": "18",
- "Work": "搬砖",
- "Name": "胡",
- "From": "Jiangxi"
- }
- >>Obj_destroy,Me
- >>Me