elementwise operation on array of arrays in Julia - arrays

I am new to Julia and I am trying to migrate from existing code in Mathematica. I am trying to do: with an array of vectors, subtract a constant vector from it. Here is what I want:
a=[[1, 2], [1, 3]]
println(a)
b=a.-[1,1]
println(b)
I want b=[[0,1],[0,2]] but it gives me error about dimension mismatch. I am a bit at a loss regarding the difference between "a list of vectors" and "a matrix" in Julia. I am not sure what is the right way to do these two different things.
I then tried broadcasting but it did not work either
a=([1, 2], [1, 3])
println(a)
b=broadcast(-,[1,1],a)
println(b)
Finally, I tried
a=([1, 2], [1, 3])
println(a)
b=a.-([1,1],)
println(b)
and it worked.
My questions:
Why don't the first two work?
Is this a hack walkaround or should I be using this in the future?

You need to use Ref to avoid vectorization on the second argument of your difference:
julia> a .- Ref([1,1])
2-element Vector{Vector{Int64}}:
[0, 1]
[0, 2]
Without that you were iterating over elements of a as well as elements of [1, 1] which ended in calculating an unvectorized difference between a vector and a scalar so it did not work.

An alternative way:
julia> broadcast(.-, a, [1, 1])
2-element Vector{Vector{Int64}}:
[0, 1]
[0, 2]
In more recent Julia versions, "dotted operators" can be used as stand-alone values of a wrapper type:
julia> .-
Base.Broadcast.BroadcastFunction(-)
which you can then broadcast.

Related

Is there any functional difference between array_upper and array_length?

The postgres docs on these 2 array functions are pretty weak.
I've tried both functions a few different ways and they seem to return the same results.
SELECT array_length(array[[1, 2], [3, 4], [5, 6]], 1);
SELECT array_upper(array[[1, 2], [3, 4], [5, 6]], 1);
SELECT array_length(array[[1, 2], [3, 4], [5, 6]], 2);
SELECT array_upper(array[[1, 2], [3, 4], [5, 6]], 2);
Yes, there is a difference. PostgreSQL array subscripts start at one by default but they don't have to:
By default PostgreSQL uses a one-based numbering convention for arrays, that is, an array of n elements starts with array[1] and ends with array[n].
[...]
Subscripted assignment allows creation of arrays that do not use one-based subscripts. For example one might assign to myarray[-2:7] to create an array with subscript values from -2 to 7.
[...]
By default, the lower bound index value of an array's dimensions is set to one. To represent arrays with other lower bounds, the array subscript ranges can be specified explicitly before writing the array contents.
In general, you need to use array_lower and array_upper instead of assuming that the array will start at 1 and end at array_length(a, n).

Algorithm Logic, Splitting Arrays

I'm not looking for a solution just pseudo code or logic that would help me derive an answer.
Given an array:
[1,2,3,4]
I want to split this into two arrays of varying lengths and contents whose sum lengths are equal to the length of the given array. It would be ideal without repetition.
Example output:
[[1],[2, 3, 4]]
[[1, 2], [3, 4]]
[[1, 3], [2, 4]]
[[1, 4],[2, 3]]
[[1, 2, 3], [4]]
[[2], [1, 3, 4]]
[[2, 4], [1, 3]]
[[3], [1, 2, 4]]
More example:
[[1, 3, 4, 6, 8], [2, 5, 7]] //this is a possible combination of 1 through 8
//array
Intuitions:
First attempt involved pushing the starting number array[i] to the result array[0], the second loop moving the index for the third loop to start iterating as is grabbed sublists. Then fill the other list with remaining indices. Was poorly conceived...
Second idea is permutations. Write an algorithm that reorganizes the array into every possible combination. Then, perform the same split operation on those lists at different indexes keeping track of unique lists as strings in a dictionary.
[1,2,3,4,5,6,7,8]
^
split
[1,2,3,4,5,6,7,8]
^
split
[1,3,4,5,6,7,8,2]
^
split
I'm confident that this will produce the lists i'm looking for. However! i'm afraid it may be less efficient than I'd like due to the need for sorting when checking for duplicates and permutations is expensive in the first place.
Please respond with how you would approach this problem, and why.
Pseudocode. The idea is to start with an item in one of the bags, and then to place the next item once in the same bag, once in the other.
function f(A):
// Recursive function to collect arrangements
function g(l, r, i):
// Base case: no more items
if i == length(A):
return [[l, r]]
// Place the item in the left bag
return g(l with A[i], r, i + 1)
// Also return a version where the item
// is placed in the right bag
concatenated with g(l, r with A[i], i + 1)
// Check that we have at least one item
if A is empty:
return []
// Start the recursion with one item placed
return g([A[0]], [], 1)
(PS see revisions for JavaScript code.)

How to convert a matrix to an array of arrays?

In How to convert an array of array into a matrix? we learned how to convert an array of arrays to a matrix. But what about the other way around? How do we go from input to output, as shown below?
input = [1 2 3; 4 5 6; 7 8 9]
output = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
If you want to make a copy of the data then:
[input[i, :] for i in 1:size(input, 1)]
If you do not want to make a copy of the data you can use views:
[view(input, i, :) for i in 1:size(input, 1)]
After some thought those are alternatives using broadcasting:
getindex.([input], 1:size(input, 1), :)
view.([input], 1:size(input, 1), :)
I add one alternative too:
mapslices(x->[x], input,2)
Edit:
Warning! Now I see that mapslices return 3x1 matrix! (you could change it: mapslices(x->[x], input,2)[:,1])
I am unsatisfied. I don't like any solution we find yet. They are too complicated (think for example how to explain it to children!).
It is also difficult to find function like mapslices in doc too. BTW there is non-exported Base.vect function which could be used instead of anonymous x->[x].
I was thinking that sometimes is more clever to use bigger hammer. So I tried to find something with DataFrames
julia> using DataFrames
julia> DataFrame(transpose(input)).columns
3-element Array{Any,1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
unfortunately there is not DataFrame.rows
result's type is Array{Any,1}
I don't think it could be very quick
I hope Julia could get us better solution! :)

Julia: Flattening array of array/tuples

In Julia vec reshapes multidimensional arrays into one-dimension arrays.
However it doesn't work for arrays of arrays or arrays of tuples.
A part from using array comprehension, is there another way to flatten arrays of arrays/tuples? Or arrays of arrays/tuples of arrays/tuples? Or ...
Iterators.flatten(x) creates a generator that iterates over each element of x. It can handle some of the cases you describe, eg
julia> collect(Iterators.flatten([(1,2,3),[4,5],6]))
6-element Array{Any,1}:
1
2
3
4
5
6
If you have arrays of arrays of arrays and tuples, you should probably reconsider your data structure because it doesn't sound type stable. However, you can use multiple calls to flatten, eg
julia> collect(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6]))
6-element Array{Any,1}:
1
2
[3, 3, 3, 3]
4
5
6
julia> collect(Iterators.flatten(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6])))
9-element Array{Any,1}:
1
2
3
3
3
3
4
5
6
Note how all of my example return an Array{Any,1}. That is a bad sign for performance, because it means the compiler could not determine a single concrete type for the elements of the output array. I chose these example because the way I read your question it sounded like you may have type unstable containers already.
In order to flatten an array of arrays, you can simply use vcat() like this:
julia> A = [[1,2,3],[4,5], [6,7]]
Vector{Int64}[3]
Int64[3]
Int64[2]
Int64[2]
julia> flat = vcat(A...)
Int64[7]
1
2
3
4
5
6
7
The simplest way is to apply the ellipsis ... twice.
A = [[1,2,3],[4,5], [6,7]]
flat = [(A...)...]
println(flat)
The output would be
[1, 2, 3, 4, 5, 6, 7].
If you use VectorOfArray from RecursiveArrayTools.jl, it uses the indexing fallback to provide convert(Array,A) for a VectorOfArray A.
julia> using RecursiveArrayTools
julia> A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> VA = VectorOfArray(A)
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
First of it acts as a lazy wrapper for doing the indexing without conversion:
julia> VA[1,3]
7
Note that columns are the separate arrays so that way it's still "column-major" (i.e. efficient to index down columns). But then it has a straight conversion:
julia> convert(Array,VA)
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
The other way to handle this conversion is to do something like hcat(A...), but that's slow if you have a lot of arrays you're splatting!
Now, you may think: what about writing a function that pre-allocates the matrix, then loops through and fills it? That's almost what convert on the VectorOfArray works, except the fallback that convert uses here utilizes Tim Holy's Cartesian machinery. At one point, I wrote that function:
function vecvec_to_mat(vecvec)
mat = Matrix{eltype(eltype(vecvec))}(length(vecvec),length(vecvec[1]))
for i in 1:length(vecvec)
mat[i,:] .= vecvec[i]
end
mat
end
but I have since gotten rid of it because the fallback was much faster. So, YMMV but that's a few ways to solve your problem.
for Julia 0.7x:
for Arrays:
flat(arr::Array) = mapreduce(x -> isa(x, Array) ? flat(x) : x,
append!, arr,init=[])
for Tuples:
flat(arr::Tuple) = mapreduce(x -> isa(x, Tuple) ? flat(x) : x,
append!, arr,init=[])
Works for arbitrary depth.
see: https://rosettacode.org/wiki/Flatten_a_list#Julia
Code for Array/Tuple:
function flatten(arr)
rst = Any[]
grep(v) = for x in v
if isa(x, Tuple) || isa(x, Array)
grep(x)
else push!(rst, x) end
end
grep(arr)
rst
end

Is there a simple way to sort an array in Crystal?

I'm new to Crystal and I find it fun to learn and work with.
What's a simple and quick way to sort an array?
Without knowing what your Array actually contains i assume it's an Array(Int32) (array of integers).
You can easily sort an array of integers like
[4, 7, 2].sort { |x, y| y <=> x } # => [7, 4, 2]
Check the array spec in Crystal core for more info https://github.com/crystal-lang/crystal/blob/bf6b743aa7649ed3ecc92dd06fde21f88460720a/spec/std/array_spec.cr#L998-L1047
you can use sort like in Ruby
puts [7,3,2,8].sort #=> [2, 3, 7, 8]

Resources