Julia: counting total number of elements in an array-of-arrays - arrays

Is there a single function in Julia that will give you the total number of elements in an array-of-arrays (or 'jagged array')?
Here's what I mean:
my_array_of_arrays = [ [1, 5], [6], [10, 10, 11] ]
I'm looking for a function such that
desired_function(my_array_of_arrays) will return 6
And if not, what's the quickest way to do this in Julia?
Thanks in advance!

One way to do it without additional dependencies would be to use sum:
julia> my_array_of_arrays = [ [1, 5], [6], [10, 10, 11] ]
3-element Array{Array{Int64,1},1}:
[1, 5]
[6]
[10, 10, 11]
julia> sum(length, my_array_of_arrays)
6
However, if you want to work more intensively with ragged arrays, you might be better off using specialized packages, such as ArraysOfArrays.jl.

sum(length, x) suggested by #MattB is a more elegant answer and it deserves being here so others can find it.
Testing:
julia> my_array_of_arrays = [ [1, 5], [6], [10, 10, 11] ]
3-element Array{Array{Int64,1},1}:
[1, 5]
[6]
[10, 10, 11]
julia> sum(length, my_array_of_arrays)
6
Note that the performance of both methods mapreduce(length, +, x) and sum(length, x) is identical since both do not materialize the data.

Related

Fill an empty array (Vector of vectors) in Julia using for loop

Given
b=[ [1,[2,3,7]],
[2,[7,2,7]],
[3,[2,3,9]] ]
a=[ [2,3,7],[7,2,7],[2,3,9] ]
I want to get b from empty vector of vectors using for loop.
b=[ [ ] ]
for i in 1:3
b[i][1]=i
b[i][2]=a[i]
end
julia> a = [[2,3,7],[7,2,7],[2,3,9]];
julia> b = enumerate(a) |> collect
3-element Vector{Tuple{Int64, Vector{Int64}}}:
(1, [2, 3, 7])
(2, [7, 2, 7])
(3, [2, 3, 9])
As the output says, this returns a Vector of Tuples. If you do need exactly a vector of vectors for some reason, you can do:
julia> b = enumerate(a) |> collect .|> collect
3-element Vector{Vector{Any}}:
[1, [2, 3, 7]]
[2, [7, 2, 7]]
[3, [2, 3, 9]]
For a tuple, just use tuple.(1:3,a), if a vector is required do vec.(1:3,a). Note that a tuple is an immutable container, so you might gain some performance benefits, and you can still change the elements of the vectors inside since vectors are mutable.
b = tuple.(1:3,a)
3-element Vector{Tuple{Int64, Vector{Int64}}}:
(1, [2, 3, 7])
(2, [7, 2, 7])
(3, [2, 3, 9])
b = vec.(1:3,a)
3-element Vector{Vector{Any}}:
[1, [2, 3, 7]]
[2, [7, 2, 7]]
[3, [2, 3, 9]]

Groovy 2D array combinations

I have a 2D array which looks like [[1, 2, 3], [10, 11]]. I want to get the next combinations: [[1, 2, 3, 10], [1, 2, 3, 11]]. The idea is to take all values from left array and combine it with each value from right array. I've tried different Groovy out of the box methods like combinations(), permutations() to get the expected result, but without any success. Please, help.
Why not simply:
def a = [[1, 2, 3], [10, 11]]
def res = a[ 1 ].collect{ a[ 0 ] + it }
assert res == [[1, 2, 3, 10], [1, 2, 3, 11]]
If one can cheat... Nesting the first list into another list can let us use .combinations() still:
def a = [[[1, 2, 3]], [10, 11]] //a[0] changed to [a[0]]
a.combinations().collect{it.flatten()} //[[1, 2, 3, 10], [1, 2, 3, 11]]
Now, if you can't store the values like that, you can still still make the change part of your code. All this assumes that the list is just a pair.
([a[0]] + a[1..<(a.size())]).combinations().collect{it.flatten()} //same result
I believe there are less unorthodox ways of doing it, but that's a quick and dirty solution.

Appending pairs of coordinates to numpy array

I need to append 1D arrays (coordinates) into a 2d array using numpy in python 3.6.
I can do this with lists using append, such as in the first example below.
mastlist =[]
i=0
for i in range (10):
i=i+1
coor = []
xcoor = i
ycoor =i*2
coor.append(xcoor)
coor.append(ycoor)
mastlist.append(coor)
print(mastlist)
But I want a more performant approach using numpy arrays. When I attempt to convert the list approach to an array (second example),
import numpy as np
i=0
for i in range (10):
i=i+1
centroid =np.append(i,i*2)
masterarray=np.append([centroid],axis=0)
print(masterarray)
print(masterarray)
I get the error below.
My error is:
TypeError: append() missing 1 required positional argument: 'values'
I would of expected an array such as:
[[1, 2], [2, 4], [3, 6], [4, 8], [5, 10], [6, 12], [7, 14], [8, 16], [9, 18], [10, 20]]
I have also fumbled with attempts using extend, vstack, and concatenate.
Any advice would be welcome.
I recommend you get single coordinate data firstly , then concatenate them. To my best knowledge, I dont think it can be done by np.append
The common method is np.concatenate, which I see it from cs231n class.
My sample codes are as follows:
import numpy as np
xcoor = np.arange(1,11,1).reshape(-1,1)
ycoor = np.arange(2,22,2).reshape(-1,1)
xycoor = np.concatenate((xcoor,ycoor),axis = 1)
print(xycoor)
Output:
[[ 1 2]
[ 2 4]
[ 3 6]
[ 4 8]
[ 5 10]
[ 6 12]
[ 7 14]
[ 8 16]
[ 9 18]
[10 20]]
Why not just use list comprehension?
import numpy as np
masterarray = np.array([[i,2*i] for i in range(1,11)])
output
array([[ 1, 2],
[ 2, 4],
[ 3, 6],
[ 4, 8],
[ 5, 10],
[ 6, 12],
[ 7, 14],
[ 8, 16],
[ 9, 18],
[10, 20]])

How to use percent notation to make an array of integers in ruby?

In ruby you can use percent notation to easily make an array of strings:
[14] pry(main)> %w(some cats ran far)
=> ["some", "cats", "ran", "far"]
Using a method found in another post I was able to make an array of strings using percent notation and then converting them into Fixnums later:
[15] pry(main)> %w(1 2 3).map(&:to_i)
=> [1, 2, 3]
But I'd really like to be able to do something like
%i(1 2 3) #=> [1 2 3]
Is this possible? Thanks :)
As cremno said, no that is not possible.
If you want strictly a range of integers, such as 1 through 10, the best method will be
(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
But if you want to specify exact integers I would do this
%w(1 5 10).map{|i| i.to_i}
# => [1, 5, 10]
But at that point I don't know why you wouldn't just do this directly...
[1, 5, 10]
Well, you can do something like this.
%i(1 2 3).map(&:to_s).map { |i| Integer(i) } #=> [1, 2, 3]
Using a range seems like it might be the easiest:
[26] pry(main)> (1..3).to_a
=> [1, 2, 3]

How to transpose an array in Python 3?

I've been scanning the forums and haven't found an answer yet that I can apply to my situation. I need to be able to take an n by n array and transpose it in Python-3. The example given is that I have this list input into the function:
[[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]] and it needs to be transposed to read:
[[4, 'a', -1], [2, 'a', -2], [1, 'a', -3]] So basically reading vertically instead of horizontally.
I CANNOT use things like zip or numpy, I have to make my own function.
Been rattling my brain at this for two nights and it's a huge headache. If anyone could help and then provide an explanation so I can learn it, I'd be grateful.
Edit:
I should add for reference sake that the argument variable is M. The function we're supposed to write is trans(M):
A one-liner:
def trans(M):
return [[M[j][i] for j in range(len(M))] for i in range(len(M[0]))]
result:
>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> trans(M)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]
# or for a non-square matrix:
>>> N = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> trans(N)
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Additional Note: If you look up the tutorial on list comprehension, one of the examples is in fact transposition of a matrix array.
A variant that should work for matrices with irregular row lengths:
m=[[3, 2, 1],
[0, 1],
[2, 1, 0]]
m_T = [ [row[c] for row in m if c < len(row)] for c in range(0, max([len(row) for row in m])) ]
Here is an in place solution that works for square matrices:
def trans(M):
n = len(M)
for i in range(n - 1):
for j in range(i + 1, n):
M[i][j], M[j][i] = M[j][i], M[i][j]
Example Usage:
def print_matrix(M):
for row in M:
for ele in row:
print(ele, end='\t')
print()
M = [[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]]
print('Original Matrix:')
print_matrix(M)
trans(M)
print('Transposed Matrix:')
print_matrix(M)
Output:
Original Matrix:
4 2 1
a a a
-1 -2 -3
Transposed Matrix:
4 a -1
2 a -2
1 a -3
y=([1,2], [3,4], [5,6])
transpose=[[row[i] for row in y] for i in range(len(y[0]))]
the output is
[[1, 3, 5], [2, 4, 6]]
You can also use the function in numpy to transpose - if you need the answer as a list it is straightforward to convert back using tolist:
from numpy import transpose
M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose(M).tolist()
the output is
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Haven't timed it (no time!) but I strongly suspect this will be a lot faster than iterators for large arrays, especially if you don't need to convert back to a list.

Resources