【问题标题】:Using a vector to subset elements within a string vector in Julia在 Julia 中使用向量对字符串向量中的元素进行子集化
【发布时间】:2025-12-31 00:25:11
【问题描述】:

我正在尝试使用 IntegerVector{Integer} 子集值的组合在 Julia 中对 Vector{String} 进行子集化。我想编写一个函数,它基本上允许 "asdf"[1:3] 的子集,其中三个参数 x[y:z] 中的每一个都是向量或单例。

这是我到目前为止所尝试的:

function substring(x::Array{String}, y::Integer, z::Integer)
  y = fill(y, length(x))
  z = fill(z, length(x))
  substring(x, y, z)
end

function substring(x::Vector{String}, y::Vector{Integer}, z::Integer)
  y = fill(y, length(x))
  substring(x, y, z)
end

function substring(x::Vector{String}, y::Integer, z::Vector{Integer})
  z = fill(z, length(x))
  substring(x, y, z)
end

function substring(x::Vector{String}, y::Vector{Integer}, z::Vector{Integer})
  for i = 1:length(x)
    x[i] = x[i][y[i]:min(z[i], length(x[i]))]
    # If z[i] is greater than the length of x[i] 
    # return the end of the string
  end
  x
end

尝试使用它:

v = string.('a':'z')
x = rand(v, 100) .* rand(v, 100) .* rand(v, 100)

substring(x, 1, 2)
# or
substring(x, 1, s)

我得到错误:

MethodError: no method matching substring(::Array{String,1}, ::Int64, ::Array{Int64,1})
Closest candidates are:
  substring(::Array{String,N}, ::Integer, !Matched::Integer) at untitled-e3b9271a972031e628a35deeeb23c4a8:2
  substring(::Array{String,1}, ::Integer, !Matched::Array{Integer,1}) at untitled-e3b9271a972031e628a35deeeb23c4a8:13
  substring(::Array{String,N}, ::Integer, !Matched::Array{Integer,N}) at untitled-e3b9271a972031e628a35deeeb23c4a8:13
  ...
 in include_string(::String, ::String, ::Int64) at eval.jl:28
 in include_string(::Module, ::String, ::String, ::Int64, ::Vararg{Int64,N}) at eval.jl:32
 in (::Atom.##53#56{String,Int64,String})() at eval.jl:50
 in withpath(::Atom.##53#56{String,Int64,String}, ::Void) at utils.jl:30
 in withpath(::Function, ::String) at eval.jl:38
 in macro expansion at eval.jl:49 [inlined]
 in (::Atom.##52#55{Dict{String,Any}})() at task.jl:60

我看到还有另一个post addressingVector{String} 类型类似的错误。我的帖子还询问了对与Vector{Integer} 相关的错误的回应。我相信对它的回应可能对像我这样发现抽象类型的实现新颖而困难的其他人有所帮助。

【问题讨论】:

  • 这是一个参数不变性的例子。类似问题见*.com/questions/21465838/…;你的问题在Vector{Integer}
  • 我想指出,虽然我的问题已被解释为类型管理问题。我真的只是在寻找一个符合标题所说的功能。在我更习惯的 R 中,答案很简单,substr(x,1,2)。我包含了上面的代码,以表明我在自己解决问题方面做出了合理的努力......如果不是太麻烦,我真的很感激答案。
  • 当然,我添加了一个解决您实际问题的答案(在 Julia 中它与在 R 中没有太大区别)。

标签: arrays string vector julia


【解决方案1】:

如果您使用的是 Julia 0.6,使用 SubString.(strs, starts, ends) 很容易做到这一点:

julia> SubString.("asdf", 2, 3)
"sd"

julia> SubString.(["asdf", "cdef"], 2, 3)
2-element Array{SubString{String},1}:
 "sd"
 "de"

julia> SubString.("asdf", 2, [3, 4])
2-element Array{SubString{String},1}:
 "sd" 
 "sdf"

在 Julia 0.5 上,您可以做同样的事情,但您必须将字符串包装在一个向量中(即它不能保留为单个标量):

julia> SubString.(["asdf"], [1, 2, 3], [2, 3, 4])
3-element Array{SubString{String},1}:
 "as"
 "sd"
 "df"

Julia 和 R 之间的主要区别在于,在 R 中,函数通常默认处理向量(广播),而在 Julia 中,您通过使用所谓的“点调用”明确指定广播行为,即f.(x, y, z)

【讨论】:

    【解决方案2】:

    只是为了明确这一点,认为它是一种非常普遍的想法。

    即使Int64 <: Integer 是真的

    Array{Int64,1} <: Array{Integer,1} 不是!


    docs on parametric-composite-types 详细解释了原因。但解释它的基本原因是因为前者Array{Int64,1} 在内存中有特定的表示(即许多连续的 64 位值),而Array{Integer,1} 必须是指向单独分配的值的指针集,这些值可能是也可能不是 64 位。

    查看类似的问答,了解可用于在 julia 0.6 中声明函数的新语法:Vector{AbstractString} function parameter won't accept Vector{String} input in julia

    【讨论】:

    • 您介意告诉我您将如何更改代码以使其正常工作吗?