Julia递归返回Any类型数组的数组而非Int64类型矩阵问题
Julia递归生成排列返回Any类型数组而非Int64矩阵的原因及解决方法
问题描述
作为Julia新手,我编写程序计算从向量1:n中可重复选取k个元素的排列,要求每个排列的和等于目标值n。代码能运行出结果,但返回的是Any类型的数组的数组,而非Int64类型的矩阵。我知道可以通过后续转换解决,但想了解为何无法直接输出目标格式。
原代码
function find_permutations_with_replacement(arr::Array{Int64,1}, n::Int64, k::Int64; current_sum::Int64=0, path=[], res=[]) # Check if we have the correct number of elements and if their sum is exactly n if length(path) == k if current_sum == n push!(res,copy(path)) end return end # Early exit if the current sum already exceeds the target sum if current_sum > n return end # Recursively explore each element in the array, allowing for repetition for i in 1:length(arr) push!(path, arr[i]) find_permutations_with_replacement(arr, n, k; current_sum=arr[i] + current_sum, path=path, res=res) pop!(path) end return res end # model parameters d = 3; # dimension maxl = 4; # maximimum level levs = collect(1:maxl); finres=[]; for trgt in d:maxl+d-1 permutations = find_permutations_with_replacement(levs, trgt, d); push!(finres,permutations); end
原因分析
默认参数的类型推断问题:
- 函数中
path=[]和res=[]的空数组,Julia无法推断其元素类型,默认会创建Vector{Any}类型的数组。后续向其中添加Int64元素时,数组类型不会自动变更,最终返回的res就是Vector{Vector{Any}}类型。 - 全局变量
finres=[]同样是Vector{Any}类型,push进去的子数组会保留原类型,导致最终finres为Vector{Vector{Vector{Any}}}。
- 函数中
数组的数组与矩阵的本质差异:
你期望的Int64类型矩阵是二维连续内存结构(Matrix{Int64}),而当前代码返回的是"数组的数组"(Vector{Vector{T}})。二者结构不同:矩阵的所有行共享同一内存块,而数组的数组是多个独立一维数组的集合,无法直接等价。只有当所有子数组长度固定(这里k是固定值),才能将其转换为矩阵。
解决方案
1. 让函数直接返回类型明确的数组
修改函数的默认参数,指定明确的类型,让Julia在初始化时就确定数组的元素类型:
function find_permutations_with_replacement(arr::Vector{Int64}, n::Int64, k::Int64; current_sum::Int64=0, path=Int64[], res=Vector{Vector{Int64}}()) if length(path) == k if current_sum == n push!(res, copy(path)) end return end if current_sum > n return end for num in arr # 直接遍历元素更简洁 push!(path, num) find_permutations_with_replacement(arr, n, k; current_sum=current_sum + num, path=path, res=res) pop!(path) end return res end # 初始化finres时指定类型 d = 3; maxl = 4; levs = collect(1:maxl); finres = Vector{Vector{Vector{Int64}}}(); for trgt in d:maxl+d-1 permutations = find_permutations_with_replacement(levs, trgt, d); push!(finres, permutations); end
此时find_permutations_with_replacement返回的是Vector{Vector{Int64}},finres是Vector{Vector{Vector{Int64}}},类型完全明确。
2. 转换为Int64矩阵(如果需要)
如果确实需要Matrix{Int64}格式,可以在得到结果后用hcat转置拼接(每个子数组对应一行):
# 以其中一个permutations为例 permutations = find_permutations_with_replacement(levs, d, d); perm_matrix = permutedims(hcat(permutations...))
这样得到的perm_matrix就是Matrix{Int64}类型,每行对应一个符合条件的排列。
内容的提问来源于stack exchange,提问作者Martin Scheffel
相关产品推荐
相关产品推荐

