Using one array to index another in Ruby - arrays

I am trying to learn Ruby, and I'm wondering how an array can be used to index another array, for example,
in Perl this is: my #x = #y[#ro], where all three variables are just generic arrays.
how can I accomplish the same thing in Ruby?

If I remember my Perl correctly, given:
my #ro = ('a', 'b', 'c', 'd', 'e');
my #y = (1, 3);
Then #ro[#y] would be ('b', 'd') so the notation is just a short form for extracting all the elements of the array #ro at the indexes in #y.
In Ruby, I'd use Array#values_at and a splat thusly:
ro = %w[a b c d e]
y = [1, 3]
x = ro.values_at(*y)
The *y splat unwraps the array and gives you its elements so ro.values_at(*y) is equivalent to ro.values_at(1, 3) in this case.

Related

Numpy array questions about .shape

I'm new to numpy, and I have some troubles in array shapes.
I want to operate the array like a matrix in matlab. However, I'm confused about the following things:
>>> b = np.array([[1,2],[3,4]])
array([[1, 2],
[3, 4]])
>>> c = b[:,1] # I want c is a column vector
>>> c.shape
(2,)
>>> d = b[1,:] # I want d is a row vector
>>> d.shape
>>> (2,)
I want to treat c and d as column vector and row vector respectively.
I don't understand why c and d have the same shape (2,).
So it troubles me in later calculations.
Could anyone help me deal with this problem. Thanks a lot !
Using a plain integer as an index returns that column/row as a true vector. This is similar to indexing a list - you only receive the element at that index. The containing dimension is stripped away:
>>> my_list = ['a', 'b', 'c', 'd']
>>> my_list[2]
'c'
Instead, you want a slice. A slice of a list is a (sub-) list, and a slice of a matrix is a matrix. With numpy, you can specify this either as slice notation using : or a sequence of indices:
>>> c = b[:,:1] # slice notation
>>> c.shape
(2, 1)
>>> d = b[[1],:] # sequence of indices
>>> d.shape
(1, 2)
Slice notation is for consecutive index ranges. For example, :1 means "everything from the start up to 1". Sequence notation is for non-consecutive index sets. For example, [0, 2] does skip index 1. If you just want a single index, sequence notation is simpler unless you are dealing with borders (first/last row/column).
You can use
c = b[:,[1]]
d = b[[1],:]
to get the vector as an explicit row/column vector:
c.shape # (1, 2)
d.shape # (2, 1)
In general, if you want your array c to be a column vector of shape (2,1), you can reshape it by:
c = c.reshape(-1,1) # c.shape --> (2, 1)
Similarly, if you want your array d to be a row vector of shape (1,2), you can reshape it by:
d = d.reshape(1,-1) # d.shape --> (1, 2)

Best way to generate all combinations in array that contain certain element in it

I know that I can easily get all the combinations, but is there a way to only get the ones that contain certain element of the list? I'll give an example.
Lets say I have
arr = ['a','b','c','d']
I want to get all combinations with length (n) containing 'a', for example, if n = 3:
[a, b, c]
[a, b, d]
[a, c, d]
I want to know if there is a better way to get it without generating all combinations. Any help would be appreciated.
I would proceed as follow:
Remove 'a' from the array
Generate all combinations of 2 elements from the reduced array
For each combination, insert the 'a' in all three possible places
You can use combination of itertools and list comprehension. Like:
import itertools
import itertools
arr = ['a', 'b', 'c', 'd']
temp = itertools.combinations(arr, 3)
result = [list(i) for i in list(temp) if 'a' in i]
print(result)
output:
[['a', 'b', 'c'], ['a', 'b', 'd'], ['a', 'c', 'd']]

Get original array indices after #combination

I am learning Ruby and one issue I have come across in a few practice problems is working with combinations from an array, but getting the original array indices instead of the actual combination as a result. To keep it simple let's just talk about pairs. I know a fast way to get all possible pairs is:
array = [a, b, c]
array.combination(2).to_a
# => [[a, b], [a, c], [b, c]]
Now let's say I want to iterate over these combinations and choose a pair that fits an arbitrary condition. It would be easy enough to return the pair itself:
...select{|pair| condition}
# => [a, c]
# assuming this pair fits the condition
but what if I want to return the indices from the original array instead?
# => [0, 2]
Is there a way of doing this using #combination ? Or would you have to find the combinations yourself in this case? If so is there a more elegant way to do it than the following(which is what I ended up doing to solve these problems)?
array.each.with_index do |s1, i1|
array[(i1 + 1)..-1].each.with_index do |s2, i2|
if condition
result = [i1, (i2 + i1 + 1)]
end
end
end
Try this:
array = ['a', 'b', 'c', 'd']
array.combination(s).to_a.reduce do |memo, pair|
if condition # I tested with pair[0] == 'a' && pair[1] == 'c'
memo = pair.map {|e| array.index(e)}
else
memo
end
end
My test of this yielded:
[0, 2]
edit
To avoid using a call to index, just compute the indexes ahead of time and then create a combination of them, selecting the one(s) that meet the condition:
(0..array.length).to_a.combination(2).to_a.select {|pair| condition}

Insert items into an array while iterating

How would I modify (add/remove elements) an array while iterating over it and have the iterator be aware of it?
For example I would think this code:
a = "1234567890".split("")
a.each_with_index{|d, i|
if d.eql?('5')
a.delete_at(i)
a.insert(i, ['A', 'B', 'C'] )
end
print d
}
would produce: 1234ABC67890 but instead produces 1234567890
Is there a workaround or different method to make this work?
(I know this example is pretty simple example but I am doing some complicated text processing where I need to insert some text when I hit a key word. I do a bunch of functions before and after I would do the expansion so doing the insert outside of the each loop [aka map!] would really complicate my code)
Actually, your code works, you just need to replace print d with print a[i] since what you're printing is the variable d not the actual array element at index i
Rather than deleting and inserting, why not change the element on that index?
a = "1234567890".split("")
a.each_with_index{|d, i|
if d.eql?('5')
a[i] = ['A','B','C']
end
print a[i] #a[i] rather than d, since d contains the old value
}
or
...
if d.eql?('5')
a[i] = ['A','B','C']
d = a[i]
end
print d
Deleting/Inserting on an Array during iterations is discourage since it may cause headaches haha... Resort to other methods if possible :)
Note:
I've just used the current logic in your code based on my understanding, and the given desired output
the array will become [1,2,3,4,['A','B','C'],6,7,8,9,0] and not [1,2,3,4,'A','B','C',6,7,8,9,0]. If you want the other, just leave a comment :)
If what you want is just to change a value in the string, you can just use .tr or .gsub to do the job
Here is one option. If you want to return array then remove join otherwise keep it to return a String
a = "1234567890".split("")
a.collect! {|i| i == '5' ? ['A', 'B', 'C'] : i }.flatten!.join #=> "1234ABC67890"
Inserting and deleting while iterating is best avoided. Some problems disappear however when iterating in reverse order:
a = "1234567890".split("")
a.reverse_each.with_index{|d, i|
if d.eql?('5')
a.delete_at(i)
a.insert(i, ['A', 'B', 'C'] )
end
}
puts a.join # => 12345ABC7890
You can't in general modify an Enumerable while iterating over its members. In most such cases, you need to construct a new Enumerable as you go.
b = []
a.each_with_index do |d, i|
if d.eql?('5')
b << 'A' << 'B' << 'C'
else
b << d
end
end

Is there a slicing operator for Matlab (Octave) structs to convert them to an array or vector of scalars and back?

In Matlab or GNU Octave I'd like to do something like this:
x=struct('a',1,'b',2,'c',[1 2;3 4])
y=x(:) % array-ification of a struct
save -ascii y.txt y
z=load('y.txt')
x(:)=z % struct-ification of an array
I want to serialize/pickle a structure and recreate it later, allowing easy read/save/manipulate in other languages. I'd prefer the intermediate form to be ascii text rather than binary to facilitate human reading/editing/debugging.
Am I forgetting some clever (:)-like slicing for structs or cell arrays?
I think what you want is something like:
x = struct('a', 1, 'b', 2, 'c', [1 2; 3 4])
save('y.txt', '-struct', 'x', '-ascii')
But I do not think you can easily recreate it from the resulting file: there is data loss (the fieldnames are lost). If you don't use the -ascii option, it can be fully recreated using:
save('y.mat', '-struct', 'x')
y = load('y.mat')
isequal(x, y) % returns true
Additionally load can only load a rectangular array of numbers of ASCII text (see http://www.mathworks.com/help/techdoc/ref/save.html and http://www.mathworks.com/help/techdoc/ref/load.html for the limitations). If you wish to keep the fields of the struct in your serialized form, you might look into the "fieldnames" function.
Yes, there is :),
x=struct('a',1,'b',2,'c',[1 2;3 4])
y=reshape([fieldnames(x) struct2cell(x)]',1,[]) % array-ification of a struct
z=struct(y{:}) % struct-ification of an array
y =
'a' [1] 'b' [2] 'c' [2x2 double]
z =
a: 1
b: 2
c: [2x2 double]

Resources