2015-07-05 3 views
3

В Julia я могу использовать promote, чтобы сделать различные типы объектов совместимыми. Например:Продвижение типа массива в Julia

>promote(1, 1.0) 
(1.0,1.0) 
>typeof(promote(1, 1.0)) 
(Float64, Float64) 

Однако, если я использую promote на массивах, он не дает мне то, что я хочу:

>promote([1], [1.0]) 
([1],[1.0]) 
>typeof(promote([1], [1.0])) 
(Array{Int64,1},Array{Float64,1}) 

То, что я хочу для Int64 массив, который будет преобразован в Float64 массив, так что я получаю что-то вроде:

>promote_array([1], [1.0]) 
([1.0],[1.0]) 
>typeof(promote_array([1], [1.0])) 
(Array{Float64,1},Array{Float64,1}) 

Здесь promote_array гипотетическая функция я выдумал. Я ищу реальную функцию, которая делает то же самое. Есть ли функция в Джулии, которая делает то, что делает promote_array?

ответ

3

Я нашел функцию Base.promote_eltype, которую я могу использовать, чтобы получить то, что я хочу:

function promote_array(arrays...) 
    eltype = Base.promote_eltype(arrays...) 
    tuple([convert(Array{eltype}, array) for array in arrays]...) 
end 

Эта функция promote_array затем дает мне выход я ищу:

>promote_array([1], [1.0]) 
([1.0],[1.0]) 
>typeof(promote_array([1], [1.0])) 
(Array{Float64,1},Array{Float64,1}) 

выше решает мою проблему, хотя существование Base.promote_eltype предполагает, что может быть уже построенное решение, о котором я еще не знаю.

+0

А не видел этого. Это практически то же самое, что и мое, за исключением использования параметрических функций для извлечения eltype. – IainDunning

+0

Эта операция выполняется для почти всех функций линейной алгебры, чтобы вы могли заглянуть в каталог 'linalg'. Там мы продвигаем тип, для которого тип элемента закрывается при арифметических операциях вычисления алгебры, например. LU требует пайков, а QR требует 2-норм. Когда правильный тип элемента был вычислен, вы можете вычислить новый массив либо с помощью 'convert (AbstractArray {Float64}, [1 0; 0 1])' или 'LinAlg.copy_oftype ([1 0; 0 1], Float64)' где последнее не гарантирует сглаживания, но определяется только в 0,4. –

4

Вот что я хотел бы сделать:

function promote_array{S,T}(x::Vector{S},y::Vector{T}) 
    U = promote_type(S,T) 
    convert(Vector{U},x), convert(Vector{U},y) 
end 

Я не уверен, что ваш случай использования точно, но следующая картина является то, что я вижу, как довольно часто требуется для кода, который имеет самый крутой ввод возможно, будучи общим:

function foo{S<:Real, T<:Real}(x::Vector{S},y::Vector{T}) 
    length(x) != length(y) && error("Length mismatch") 
    result = zeros(promote_type(S,T), length(x)) 
    for i in 1:length(x) 
     # Do some fancy foo-work here 
     result[i] = x[i] + y[i] 
    end 
    return result 
end 
Смежные вопросы