Julia: Cannot append tuple to array - arrays

I would like to have an array of tuples. However it seems I cannot append a tuple to it. Here is a minimal code example that raises the error.
julia> a = [(1,1),(2,2)]
2-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 2)
julia> append!(a, (3,3) )
ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type Tuple{Int64,Int64}
This may have arisen from a call to the constructor Tuple{Int64,Int64}(...),
since type constructors fall back to convert methods.
Stacktrace:
[1] _append!(::Array{Tuple{Int64,Int64},1}, ::Base.HasLength, ::Tuple{Int64,Int64}) at ./array.jl:644
[2] append!(::Array{Tuple{Int64,Int64},1}, ::Tuple{Int64,Int64}) at ./array.jl:637
Is something wrong with my syntax? I don't get why it complains that it has to convert a number to a tuple. What gives?

append! adds all of the individual elements of another collection to the existing object. Julia raises the error here because (3, 3) is a collection of two integers and it cannot reconcile an individual integer of type Int64 with the array's Tuple{Int64,Int64} type.
The method you need is push!, which will add one or more individual items to an existing collection:
julia> push!(a, (3, 3))
3-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 2)
(3, 3)
The individual item, the tuple (3, 3), was successfully pushed onto the array a.
To accomplish the same task with append!, the tuple needs to be contained in a collection of some sort itself, such as an array:
julia> append!(a, [(4, 4)])
4-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 2)
(3, 3)
(4, 4)
This is documented on the collections page here.

Related

How to do a cartesian product of a variable number of lists in Julia?

For each value j in the set {1, 2, ..., n} where the value of n can vary (it is some variable in my program that can be different depending on the inputs from the user), I have an array A_j. I would like to obtain the cartesian product of all the arrays A_j, so that I can then iterate through that cartesian product (taking one element from each A_1, A_2, ... A_n to get a tuple (a_1, a_2, ..., a_n) in A_1 x A_2 x ... x A_n). How would I accomplish this in Julia?
Use Iterators.product:
help?> Iterators.product
product(iters...)
Return an iterator over the product of several iterators. Each generated
element is a tuple whose ith element comes from the ith argument iterator.
The first iterator changes the fastest.
Examples
≡≡≡≡≡≡≡≡≡≡
julia> collect(Iterators.product(1:2, 3:5))
2×3 Matrix{Tuple{Int64, Int64}}:
(1, 3) (1, 4) (1, 5)
(2, 3) (2, 4) (2, 5)

Build array iterating over multiple indices in Julia

I want to obtain the following result with a more elegant syntax
julia> collect(Iterators.flatten([[(x,y) for y in 1:x] for x in 1:3]))
6-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
(3, 3)
I tried something like [(x,y) for y in 1:x, x in 1:3] but I get ERROR: UndefVarError: x not defined.
Just reverse the order of variables like this:
julia> [(x,y) for x in 1:3 for y in 1:x]
6-element Array{Tuple{Int64,Int64},1}:
(1, 1)
(2, 1)
(2, 2)
(3, 1)
(3, 2)
(3, 3)
I used to have also been struggled to remember the variable order. Until one day someone told me a secret: just treat the order of for loop in the list comprehension as usual except that the body is moved to the front.
For example, in normal order we write:
for x in 1:3
for y in 1:x
# do sth
end
end
Now we move the body part to the front and we have [ #= do sth =# for x in 1:3 for y in 1:x]

Find total number of ways possible to create an array of size M

Suppose I have M = 2 and N = 5 and K = 2 where
M = size of array
N = Maximum number that can be present as an array element
K = Minimum number that can be present as an array element.
So how do I find the number of possible ways to create an array using the above conditions. Also the current number should be not be greater than the previous element.
The arrays created using the above conditions are
[5,5],[5,4],[5,3],[5,2],[4,4],[4,3],[4,2],[3,3],[3,2],[2,2]
i.e 10 array can be created from the above conditions.
I tried doing it by using combinations and factorials, but not getting the desired output. Any help would be appreciated.
Assuming you are just interested in the number of combinations the formula is -
(N-K+M)!/(M!(N-K+1)!)
See more here
This is known as a combinations_with_replacement: combination because the order doesn't matter (or it would be a permutation), and with replacement because elements can be repeated, like [5, 5].
list(itertools.combinations_with_replacement(range(2, 6), 2))
# [(2, 2), (2, 3), (2, 4), (2, 5), (3, 3), (3, 4), (3, 5), (4, 4), (4, 5), (5, 5)]
If you want the exact ones you listed, you will have to reverse each element, and the list itself.
list(reversed([tuple(reversed(element)) for element in itertools.combinations_with_replacement(range(2,6), 2)]))

NumPy array loses dimension upon assignment/copy, why?

I have the following code:
print(type(a1), a1.shape)
a2 = a1 #.reshape(-1,1,2) this solves my problem
print(type(a2), a2.shape)
The output is:
<class 'numpy.ndarray'> (8, 1, 2)
<class 'numpy.ndarray'> (8, 2)
I know the (commented out) reshape solves my problem, however, I'd like to understand why a simple assignment results in losing the central dimension of the array.
Does anybody know what is going on? Why referring to the array with another name changes its dimensions?
Looking at the openCV script mentioned in the comments, the reshape to three dimensions is necessary because a dimension is being lost via Boolean indexing, and not by the assignment alone.
The names of the arrays in that script which motivated the question are p0 and good_new.
Here is a breakdown of the operations in that script:
p0 is a 3D array with shape (17, 1, 2).
The line:
p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
creates new arrays, with array p1 having shape (17, 1, 2) and array st having shape (17, 1).
The assignment good_new = p1[st==1] creates a new array object by a Boolean indexing operation on p1. This is a 2D array has shape (17, 2). A dimension has been lost through the indexing operation.
The name p0 needs to be assigned back to the array data contained in good_new, but p0 also needs to be 3D. To achieve this, the script uses p0 = good_new.reshape(-1, 1, 2).
For completeness, it is worth summarising why the Boolean indexing operation in step (3) results in a dimension disappearing.
The Boolean array st == 1 has shape (17, 1) which matches the initial dimensions of p1, (17, 1, 2).
This means that the selection occurs in the second dimension of p1: the indexer array st == 1 is determining which arrays of shape (2,) should be in the resulting array. The final array will be of shape (n, 2), where n is the number of True values in the Boolean array.
This behaviour is detailed in the NumPy documentation here.
I am not sure why your are getting this.but it should not return like this.Can you please share how your a1 has been created.
I tried like below but not able to re create it
a1=np.ones((8,1,2),dtype=np.uint8)
print(type(a1), a1.shape)
<class 'numpy.ndarray'> (8, 1, 2)
a2=a1
print(type(a2), a2.shape)
<class 'numpy.ndarray'> (8, 1, 2)`

Modifying member values of composite types in an array

In Julia (0.3.0-rc1), when I fill an array with instances of a composite type and update a member of a single instance, all instances in the array get updated. Is this the intended behaviour and, if so, how should I change the value of just a single element in the array?
The code in question:
type Foo
x :: Int
y :: Int
end
arr = fill(Foo(2, 4), 3)
arr[2].x = 5
I expect [Foo(2, 4), Foo(5, 4), Foo(2, 4)] but instead I get [Foo(5, 4), Foo(5, 4), Foo(5, 4)]. What am I doing wrong? Should I always update the entire element, as in arr[2] = Foo(5, 4) (which gives the expected results)? TIA.
You created one instance of Foo and filled the array with references to this one instance.
You probably want arr = [Foo(2,4) for i in 1:3] which will create a new copy of Foo(2,4) for every index`.

Resources