在 Julia 中生成具有两个值的项目的所有组合?
Generate all combinations of items with two values in Julia?
我有 m
件商品。每个项目都是一对两个值。例如,对于 m=4
,我有矩阵:
julia> valid_pairs = [0 1;
1 2;
1 2;
2 3];
我想生成四个项目的所有组合,其中每个项目 i
只能取 valid_pairs[i, :]
中的值。基于前面的例子,我想要:
julia> all_combs
4x16 Array{Int,2}
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3
我觉得这可以使用 Combinatorics.jl
轻松完成。
虽然我使用了Combinatorics.jl
,但我所做的是:
using Combinatorics
m = 4
combs = combinations(1:m) |> collect
L = length(combs)
all_combs = zeros(Int, m, L+1)
for j in 1:L
for i in 1:m
if !in(i, combs[j])
all_combs[i, j] = valid_pairs[i, 1]
else
all_combs[i, j] = valid_pairs[i, 2]
end
end
end
all_combs[:, end] = valid_pairs[:, 1]
顺序不一样,但是
julia> [collect(x) for x in Iterators.product(eachrow(valid_pairs)...)]
2×2×2×2 Array{Array{Int64,1},4}:
[:, :, 1, 1] =
[0, 1, 1, 2] [0, 2, 1, 2]
[1, 1, 1, 2] [1, 2, 1, 2]
[:, :, 2, 1] =
[0, 1, 2, 2] [0, 2, 2, 2]
[1, 1, 2, 2] [1, 2, 2, 2]
[:, :, 1, 2] =
[0, 1, 1, 3] [0, 2, 1, 3]
[1, 1, 1, 3] [1, 2, 1, 3]
[:, :, 2, 2] =
[0, 1, 2, 3] [0, 2, 2, 3]
[1, 1, 2, 3] [1, 2, 2, 3]
应该做的。如果你真的想要一个矩阵(二维数组),那么你可以hcat
之前的答案,或者直接做
julia> reduce(hcat, collect(x) for x in Iterators.product(eachrow(valid_pairs)...))
4×16 Array{Int64,2}:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
编辑:旁注,我会将这些对定义为元组以阐明正在发生的事情,比如
valid_pairs = [(0,1), (1,2), (1,2), (2,3)]
我不会创建 2D(或 4D,或 m-D)数组,而是
comb_pairs = Iterators.product(valid_pairs...)
然后为您提供所有对组合的 lazy 版本,这样您就可以对其进行迭代而无需先实际创建它,这应该更有效(并且看起来更干净) 我觉得。
我有 m
件商品。每个项目都是一对两个值。例如,对于 m=4
,我有矩阵:
julia> valid_pairs = [0 1;
1 2;
1 2;
2 3];
我想生成四个项目的所有组合,其中每个项目 i
只能取 valid_pairs[i, :]
中的值。基于前面的例子,我想要:
julia> all_combs
4x16 Array{Int,2}
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
2 3 2 3 2 3 2 3 2 3 2 3 2 3 2 3
我觉得这可以使用 Combinatorics.jl
轻松完成。
虽然我使用了Combinatorics.jl
,但我所做的是:
using Combinatorics
m = 4
combs = combinations(1:m) |> collect
L = length(combs)
all_combs = zeros(Int, m, L+1)
for j in 1:L
for i in 1:m
if !in(i, combs[j])
all_combs[i, j] = valid_pairs[i, 1]
else
all_combs[i, j] = valid_pairs[i, 2]
end
end
end
all_combs[:, end] = valid_pairs[:, 1]
顺序不一样,但是
julia> [collect(x) for x in Iterators.product(eachrow(valid_pairs)...)]
2×2×2×2 Array{Array{Int64,1},4}:
[:, :, 1, 1] =
[0, 1, 1, 2] [0, 2, 1, 2]
[1, 1, 1, 2] [1, 2, 1, 2]
[:, :, 2, 1] =
[0, 1, 2, 2] [0, 2, 2, 2]
[1, 1, 2, 2] [1, 2, 2, 2]
[:, :, 1, 2] =
[0, 1, 1, 3] [0, 2, 1, 3]
[1, 1, 1, 3] [1, 2, 1, 3]
[:, :, 2, 2] =
[0, 1, 2, 3] [0, 2, 2, 3]
[1, 1, 2, 3] [1, 2, 2, 3]
应该做的。如果你真的想要一个矩阵(二维数组),那么你可以hcat
之前的答案,或者直接做
julia> reduce(hcat, collect(x) for x in Iterators.product(eachrow(valid_pairs)...))
4×16 Array{Int64,2}:
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3
编辑:旁注,我会将这些对定义为元组以阐明正在发生的事情,比如
valid_pairs = [(0,1), (1,2), (1,2), (2,3)]
我不会创建 2D(或 4D,或 m-D)数组,而是
comb_pairs = Iterators.product(valid_pairs...)
然后为您提供所有对组合的 lazy 版本,这样您就可以对其进行迭代而无需先实际创建它,这应该更有效(并且看起来更干净) 我觉得。