我在Julia 1.0中具有以下结构:
mutable struct Metadata
id::Int64
res_id::Int64
end
这样我就可以创建一个这样的数组,其中id
总是递增1,但是res_id
有时只是递增,就像这样:
data = [
Metadata(1, 1),
Metadata(2, 1),
Metadata(3, 1),
Metadata(4, 2),
Metadata(5, 2),
Metadata(6, 2),
...]
我想要做的是能够遍历此Array,但是基于res_id
(基于res_id
的所有数据都是1,然后是2,等等)来获取块。所需的行为将是这样的:
for res in iter_res(data)
println(res)
end
julia>
[Metadata(1, 1), Metadata(2, 1), Metadata(3, 1)]
[Metadata(4, 2), Metadata(5, 2), Metadata(6, 2)]
考虑到我通常还需要遍历数组以逐个元素地获取数据,我该如何在Julia 1.0中做到这一点?
答案 0 :(得分:0)
julia> mutable struct Metadata
id::Int64
res_id::Int64
end
julia> data = [
Metadata(1, 1),
Metadata(2, 1),
Metadata(3, 1),
Metadata(4, 2),
Metadata(5, 2),
Metadata(6, 2),
];
julia> for res in (filter(x -> x.res_id == i, data) for i in 1:2)
println(res)
end
Metadata[Metadata(1, 1), Metadata(2, 1), Metadata(3, 1)]
Metadata[Metadata(4, 2), Metadata(5, 2), Metadata(6, 2)]
答案 1 :(得分:0)
从变量名看来,您似乎正在从某些计算过程中收集数据。通常,您为此目的使用DataFrame
。
using DataFrames
data = DataFrame(id=[1,2,3,4,5,6],res_id=[1,1,1,2,2,2])
for group in groupby(data,:res_id)
println(group)
end
这将产生:
3×2 SubDataFrame{Array{Int64,1}}
│ Row │ id │ res_id │
│ │ Int64 │ Int64 │
├─────┼───────┼────────┤
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 1 │
│ 3 │ 3 │ 1 │
3×2 SubDataFrame{Array{Int64,1}}
│ Row │ id │ res_id │
│ │ Int64 │ Int64 │
├─────┼───────┼────────┤
│ 1 │ 4 │ 2 │
│ 2 │ 5 │ 2 │
│ 3 │ 6 │ 2 │
这对于进一步处理结果也更加方便。
答案 2 :(得分:0)
我最终如何解决该问题:
function iter(data::Vector{Metadata}; property::Symbol = :res_id)
#GET UNIQUE VALUES FOR THIS PROPERTY
up = Vector{Any}()
for s in data
getproperty(s, property) in up ? nothing : push!(up, getproperty(s, property))
end
#GROUP ELEMENTS BASED ON THE UNIQUE VALUES FOR THIS PROPERTY
f = Vector{Vector{Metadata}}()
idx::Int64 = 1
cmp::Any = up[idx]
push!(f, Vector{Metadata}())
for s in data
if getproperty(s, property) == cmp
push!(f[idx], s)
else
push!(f, Vector{Metadata}())
idx += 1
cmp = up[idx]
push!(f[idx], s)
end
end
return f
end
这使我可以容纳“跳过的” res_id(例如从1跳到3等),甚至可以按除res_id之外的其他将来特征(例如字符串)或Int64以外的类型对Metadata对象进行分组。有效,尽管它可能不是很有效。
然后您可以通过以下方式遍历Vector {Metadata}:
for r in iter(rs)
println(res)
end
答案 3 :(得分:0)
在Julia 1+中,应该通过实现Base.iterate(::YourType)
来获得起始迭代,并通过Base.iterate(::YourType, state)
来实现基于某些state
的其他迭代来实现。完成后,这些方法应返回nothing
,否则返回(result, state)
元组。
使用... p迭代YourType
for i in x
# stuff
end
是写作的简写
it = iterate(x)
while it !== nothing
i, state = it
# stuff
it = iterate(x, state)
end
有关详细信息,请参见manual。
答案 4 :(得分:-1)
听起来像您需要一个groupBy
函数。这是Haskell中供参考的工具
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs