我正在使用IDL 8.4。我想使用isa()函数来确定read_csv()读取的输入类型。我想使用/ number,/ integer,/ float和/ string作为一些字段,我想确保浮点数,其他是整数和其他我不在乎。我可以这样做,但它对人眼来说不太可读。
str = read_csv(filename, header=inheader)
; TODO check header
if not isa(str.(0), /integer) then stop
if not isa(str.(1), /number) then stop
if not isa(str.(2), /float) then stop
我希望我能做类似
的事情expected_header = ['id', 'x', 'val']
expected_type = ['/integer', '/number', '/float']
str = read_csv(filename, header=inheader)
if not array_equal(strlowcase(inheader), expected_header) then stop
for i=0l,n_elements(expected_type) do
if not isa(str.(i), expected_type[i]) then stop
endfor
以上不起作用,因为'/ integer'是字面意思的,我猜isa()正在寻找命名结构。你怎么能做类似的事情?
理想情况下,我想根据从文件中读取的标题来选择预期类型,这样只要标题指定了期望的字段,脚本仍然有用。
编辑:
我的初步解决方案是为ISA()编写一个包装器。不是很漂亮,但做了我想要的......如果有更清洁的解决方案,请告诉我。
另外,read_csv被定义为只返回long,long64,double和string中的一个,所以我可以编写函数来测试这个限制。但我只想让它一般工作,以便我可以将它们重用于其他类似的情况。
function isa_generic,var,typ
; calls isa() http://www.exelisvis.com/docs/ISA.html with keyword
; if 'n', test /number
; if 'i', test /integer
; if 'f', test /float
; if 's', test /string
if typ eq 'n' then return, isa(var, /number)
if typ eq 'i' then then return, isa(var, /integer)
if typ eq 'f' then then return, isa(var, /float)
if typ eq 's' then then return, isa(var, /string)
print, 'unexpected typename: ', typ
stop
end
答案 0 :(得分:1)
IDL具有一些有限的反射能力,这将完全符合您的要求:
expected_types = ['integer', 'number', 'float']
expected_header = ['id', 'x', 'val']
str = read_csv(filename, header=inheader)
if ~array_equal(strlowcase(inheader), expected_header) then stop
foreach type, expected_types, index do begin
if ~isa(str.(index), _extra=create_struct(type, 1)) then stop
endforeach
如果在你的情况下这真的“更容易阅读”,这是有争议的,因为只有三种情况需要测试。如果有500个案例,那就比编写500个略有不同的行要清晰得多。
这段剪辑使用了一些相当深奥的IDL功能,所以让我解释一下发生了什么:
expected_types
只是(字符串)关键字名称的列表,按照它们的使用顺序。
foreach
部分迭代expected_types
,将关键字字符串放入type
变量,迭代计入index
。
这相当于使用for index = 0, n_elements(expected_types) - 1 do
然后使用expected_types[index]
而不是type
,但foreach
循环更容易阅读恕我直言。参考here。
_extra
是一个特殊关键字,可以传递结构,就像它是一组关键字一样。每个结构的标签都被解释为关键字。参考here。
create_struct
函数接受一对或多对(字符串)标记名称和(任何类型)值,然后返回具有这些标记名称和值的结构。参考here。
最后,我将not
(bitwise not)替换为~
(logical not)。这个步骤与foreach
vs for
一样,在这种情况下不是必需的,但在调试某些类型的代码时可以避免头痛,这些区别很重要。
-
像这样的反光能力可以做得非常多,而且非常方便。他们是其他语言的工作马,但IDL程序员似乎并没有那么多使用它们。以下是我在IDL中使用的常见反射功能的快速列表,其中包含每个文档的链接:
create_struct
- 根据(字符串)标记名称和值创建结构。n_tags
- 获取结构中的标签数量。_extra
, _strict_extra
, and _ref_extra
- 按结构或参考传递关键字。call_function
- 通过其(字符串)名称调用函数。call_procedure
- 按其(字符串)名称调用过程。call_method
- 按(字符串)名称调用(对象的)方法。execute
- 运行存储在字符串中的完整IDL命令。注意:使用execute
功能非常小心。它将盲目地执行您(或用户,文件,Web表单等)提供的任何IDL语句。永远不要将不受信任的或Web用户输入提供给IDL execute
函数。
答案 1 :(得分:0)
您无法像这样访问关键字,但typename
的{{1}}参数可能很有用。这是未经测试的,但应该有效:
ISA