【问题标题】:convert Julia expression to array?将 Julia 表达式转换为数组?
【发布时间】:2021-10-24 01:45:47
【问题描述】:

我得到一个保存为字符串的列表,并尝试解析它以供使用。我可以使用 Meta.parse 将字符串转换为表达式:

li = db.list
print(typeof(d[1]),d[1])
>> String
   ["apple", "banana", "coconut"]

parsed_li = Meta.parse(d[1])
print(typeof(parsed_li), parsed_li)
>> Expr
   ["apple", "banana", "coconut"]

但我似乎不能像普通列表那样使用它;例如,对于普通列表,我可以通过索引访问元素,但无法访问 Expr 对象的索引:

normal_li = ["apple", "banana", "coconut"]
print(normal_li[1])
>> apple

print(parsed_li[1])
>>
MethodError: no method matching getindex(::Expr, ::Int64)

Stacktrace:
 [1] top-level scope at In[214]:8

我一直在修修补补,不知道我在这里缺少什么!

【问题讨论】:

    标签: julia


    【解决方案1】:

    依靠Meta.parse() 来解析你的输入数据既低效又不安全(恶意代码总是可以插入到输入数据中,你可能会在上面做eval 等等)。您宁愿使用专为它设计的工具。在您的情况下,请注意,此数据可以被视为有效的 JSON 格式,可以按如下方式读取:

    
    julia> str = """["apple", "banana", "coconut"]"""
    "[\"apple\", \"banana\", \"coconut\"]"
    
    julia> using JSON3
    
    julia> JSON3.read(str)
    3-element JSON3.Array{String, Base.CodeUnits{UInt8, String}, Vector{UInt64}}:
     "apple"
     "banana"
     "coconut"
    
    julia> collect(JSON3.read(str))
    3-element Vector{String}:
     "apple"
     "banana"
     "coconut"
    

    如果您信任输入数据(通常您永远不应该),您可以采用不安全的方式:

    julia> eval(Meta.parse(str))
    3-element Vector{String}:
     "apple"
     "banana"
     "coconut"
    

    如果您想在没有eval 的情况下提取信息,可以使用Expr 对象的args 字段来完成 - 但是每次处理的方式都很大程度上取决于数据结构:

    julia> Meta.parse(str).args
    3-element Vector{Any}:
     "apple"
     "banana"
     "coconut"
    

    【讨论】:

    • 关于恶意输入的要点。对Expr 头部的表面检查甚至不足以保证eval 的安全性。例如,parsed_li.headvect,人们可能会认为“它不是一个巨大的代码块或方法,它只是一个数组”。然而,这也是一个数组:["apple", delete_all_your_files_and_steal_your_cat(), "coconut"].
    【解决方案2】:

    它在docs page 中很远:evaled_li = eval(parsed_li) 将是一个字符串向量。

    【讨论】:

      【解决方案3】:

      Expr 不是类似列表的数据结构。

      引自doc

      Expr

      在已解析的 julia 代码 (AST) 中表示复合表达式的类型。 每个表达式由一个 head Symbol 组成,用于标识哪种 它是表达式(例如调用、for 循环、条件语句等), 和子表达式(例如调用的参数)。 子表达式存储在名为argsVector{Any} 字段中。

      如果您愿意,您仍然可以通过 args 字段访问这些元素。

      【讨论】:

      • 是的,我的问题是它是否可以转换为数组
      • 嗯,我认为很明显 args 字段是您在这种特定情况下想要的?否则,我在这里没有看到将二叉树结构转换为列表的任何意义。
      • parsed_li.args 实际上是 Any 的 Vector。一个 Expr 还没有被评估,所以它的args 将包含文字(字符串、Int、Float64)、符号或其他 Expr 的向量。由于您的数组一开始只包含字符串,这实际上就足够了。
      猜你喜欢
      • 2016-04-26
      • 2021-03-28
      • 2015-06-28
      • 1970-01-01
      • 2010-11-03
      • 2022-01-09
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多