4

10,000 を超える Float64 値のペアを含む配列の配列があります。このようなもの:

v = [[rand(),rand()], ..., [rand(),rand()]]

そこから2列の行列を取得したい。サイクルですべてのペアをバイパスすることは可能です。面倒に見えますが、ほんの一瞬で結果が得られます。

x = Vector{Float64}()
y = Vector{Float64}()
for i = 1:length(v)
    push!(x, v[i][1])
    push!(y, v[i][2])
end
w = hcat(x,y)

このタスクpermutedims(reshape(hcat(v...), (length(v[1]), length(v))))で見つけた を使用したソリューションは、よりエレガントに見えますが、Julia を完全に中断し、セッションを再起動する必要があります。6 年前は最適だったのかもしれませんが、現在は大規模な配列の場合は機能していません。コンパクトで高速なソリューションはありますか?

4

3 に答える 3

11

これがあなたにとって十分に短く効率的であることを願っています:

 getindex.(v, [1 2])

より簡単に消化したい場合は、次のようにします。

[v[i][j] for i in 1:length(v), j in 1:2]

また、hcatソリューションは次のように記述できます。

permutedims(reshape(reduce(hcat, v), (length(v[1]), length(v))));

Julia をハングアップさせるべきではありません (確認してください - 私にとってはうまくいきます)。

@Antonello:これが機能する理由を理解するには、より簡単な例を考えてください:

julia> string.(["a", "b", "c"], [1 2])
3×2 Matrix{String}:
 "a1"  "a2"
 "b1"  "b2"
 "c1"  "c2"

Vector ["a", "b", "c"]列と 1 行をブロードキャストしていますMatrix [1 2]。ポイントは[1 2]Matrix. したがって、ブロードキャストで行 (ベクターによって強制) と列 ( a によって強制) の両方を拡張しますMatrix。このような拡張を行うには、[1 2]行列が正確に 1 つの行を持つことが重要です。これで分かりやすくなりましたか?

于 2021-05-17T18:11:06.823 に答える
1

これまでに投稿されたさまざまなソリューションのベンチマーク...

using BenchmarkTools
# Creating the vector
v = [[i, i+0.1] for i in 0.1:0.2:2000]

M1 = @btime vcat([[e[1] e[2]] for e in $v]...)
M2 = @btime getindex.($v, [1 2])
M3 = @btime [v[i][j] for i in 1:length($v), j in 1:2]
M4 = @btime permutedims(reshape(reduce(hcat, $v), (length($v[1]), length($v))))
M5 = @btime permutedims(reshape(hcat($v...), (length($v[1]), length($v))))

function original(v)
    x = Vector{Float64}()
    y = Vector{Float64}()
    for i = 1:length(v)
        push!(x, v[i][1])
        push!(y, v[i][2])
    end
    return hcat(x,y)
end
function mat(v)
    M = Matrix{eltype(eltype(v))}(undef, length(v), 2)
    for i in eachindex(v)
        M[i, 1] = v[i][1]
        M[i, 2] = v[i][2]
    end
    return M
end
function mat_simpler(v)
    M = Matrix{eltype(eltype(v))}(undef, length(v), 2)
    for (i, x) in pairs(v)
        M[i, 1], M[i, 2] = x
    end
    return M
end

M6 = @btime original($v)
M7 = @btime mat($v) 
M8 = @btime mat($v)

M1 == M2 == M3 == M4 == M5 == M6 == M7 == M8 # true

出力:

1.126 ms (10010 allocations: 1.53 MiB)       # M1
  54.161 μs (3 allocations: 156.42 KiB)      # M2
  809.000 μs (38983 allocations: 765.50 KiB) # M3
  98.935 μs (4 allocations: 312.66 KiB)      # M4
  244.696 μs (10 allocations: 469.23 KiB)    # M5
219.907 μs (30 allocations: 669.61 KiB)      # M6
34.311 μs (2 allocations: 156.33 KiB)        # M7
34.395 μs (2 allocations: 156.33 KiB)        # M8

ベンチマーク コードのドル記号は@btime、ベクトルをローカル変数と見なすことを強制するためのものであることに注意してください。

于 2021-05-19T06:25:18.913 に答える