Other ways of converting part of array to subarray in Ruby? - arrays

When parsing CSV file I need to combine fields of a row into an array starting from 4th field (3rd array element). I want to manipulate each row as in example below:
Original array:
array1 = [1,2,3,4,5]
Changed array:
array2 = [1,2,3,[4,5]]
My code is here:
array1[0..2].push(array1[3..array1.length])
=> [1, 2, 3, [4, 5]]
My question is: Is there a better/cleaner/simpler way to convert part of an array into subarray?

There is! You can do this
a = a[0..2] + [a[3..-1]]. In ruby + can be used to concatenate arrays. Additionally, n..-1 gives you elements n to the end of the array. As a caveat, + is slower and more expensive than concat so if you were to do a[0..2].concat([a[3..-1]) it will be cheaper and faster.

Related

Add Array in single line to new file and load Array in single line

Hey I'm writing a simple game, where I want to save progress and load it at another point.
One one the elements to save is an array. I want to save this array in one single line as an array and also load it again as an array, but it only takes the first element and the following elements overwrite further content
Example (wrong) - Save Data
player_1 = "name"
array = [1, 2, 3]
count = 1000
File.open("game.txt", "w+") do |file|
file.puts player_1
file.puts array
file.puts count
end
Example (wrong) - Load Data
file_data = File.open("game.txt").readlines.map(&:chomp)
player_1 = file_data[0]
array = file_data[1]
count = file_data[2]
OUTPUT: TEXTFILE
name
1
2
3
1000
So I converted the array to a string and write it in text-file (it works but seems inconvenient)
to save the array
file.puts double_checker.to_s
# Output: String
"[1, 2, 3]"
to load the array (load string from text file, delete special chars, convert it back to array, convert elements to integers)
# Converts String back to Array, digits convert to Integers
double_checker = double_checker.delete(" []").split(",").map { |s| s.to_i }
# Output: Array
[1, 2, 3]
Now my question: Is there a way to store the array directly into to text file (in one line) and read it the same way, so I can store the array straight into a variable?
Or is it only possible to store Strings into a text file?
I'm trying to figure out how I can use write/read to save and load files for example a game progress.
One option would is to use Marshal::dump and Marshal::load.
player_1 = "name"
array = [1, 2, 3]
count = 1000
File.open("game.txt", 'wb') do |f|
f.write(Marshal.dump([player_1, array, count]))
end
#=> 28
player_1, array, count = Marshal.load(File.binread("game.txt"))
#=> ["name", [1, 2, 3], 1000]
Note that it is not guaranteed that an object serialized using dump with one version of Ruby will be readable with load with a later version of Ruby. On the other hand, Marshal can be used to serialize a wide range of Ruby objects.
"The marshaling library converts collections of Ruby objects into a byte stream", which is why Marshal's serialized objects should be written to and read from binary files.
Another option is to use JSON#generate and JSON#parse.
require 'json'
File.write("game.txt", JSON.generate([player_1, array, count]))
#=> 21
player_1, array, count = JSON.parse(File.read("game.txt"))
#=> ["name", [1, 2, 3], 1000]
One can alternatively use JSON::Ext::Generator::GeneratorMethods::Array#to_json to serialize the array:
player_1, array, count].to_json
#=> "[\"name\",[1,2,3],1000]"

How to initialize a particular numpy array element value with a set of elements?

I have a code in which I want to create a multidimensional array of numpy with each element being another array of 3 elements of row vector here is how it looks:
a1=np.ndarray([4,4])
for i in range(4):
for j in range(4):
a1[i,j]=[2,2,2]
Now when I try to do so, I get an error:
ValueError: setting an array element with a sequence.
Please tell me where I went wrong.
Basically, my aim is to create a numpy ndarray( and not asarray or array) like this:
This is just a rough example of what I want to do.
[[1,1,1],[2,2,2],[3,3,3]
[4,4,4],[5,5,5],[6,6,6]
[1,2,3],[4,5,6],[1,2,4]]
The 3 element vector at every i, j location forms a third dimension. Thus the shape of the array should be [4, 4, 3] - the third dimension contains 3 elements.
a1 = np.ndarray([4, 4, 3])
...
your final array will have (4,4,3) shape. so you must reserve this room :
a1=np.empty((4,4,3),dtype=int)
# or np.ndarray((4,4,3),int)
for i in range(4):
for j in range(4):
a1[i,j]=[i,j,i+j] # for exemple

collect all elements and indices of an array in two separate arrays in Ruby

Suppose I have an array array = [1,2,3,4,5]
I want to collect all the elements and indices of the array in 2 separate arrays like
[[1,2,3,4,5], [0,1,2,3,4]]
How do I do this using a single Ruby collect statement?
I am trying to do it using this code
array.each_with_index.collect do |v,k|
# code
end
What should go in the code section to get the desired output?
Or even simpler:
[array, array.each_index.to_a]
I like the first answer that was posted a while ago. Don't know why the guy deleted it.
array.each_with_index.collect { |value, index| [value,index] }.transpose
Actually I am using an custom vector class on which I am calling the each_with_index method.
Here's one simple way:
array = [1,2,3,4,5]
indexes = *array.size.times
p [ array, indexes ]
# => [[1, 2, 3, 4, 5], [0, 1, 2, 3, 4]]
See it on repl.it: https://repl.it/FmWg

Find the index by current sort order of an array in ruby

If there is an array
array A = ["a","b","c","d"] #Index is [0,1,2,3]
And it's sorted to.
array A = ["d","c","b","a"]
I need an array that returns me the updated index based on the sorted order
[3,2,1,0]
I'm trying to find a solution to this ruby
UPDATE to the question
If a is sorted to
array A = ["d","b","c","a"] #not a pure reverse
Then the returned index array should be
[3,1,2,0]
You need to create a mapping table that preserves the original order, then use that order to un-map the re-ordered version:
orig = %w[ a b c d ]
orig_order = orig.each_with_index.to_h
revised = %w[ d c b a ]
revised.map { |e| orig_order[e] }
# => [3, 2, 1, 0]
So long as your elements are unique this will be able to track any shift in order.
Here is one way to do this:
original_array = ["a","b","c","d"]
jumbled_array = original_array.shuffle
jumbled_array.map {|i| original_array.index(i)}
#=> [1, 3, 0, 2]
Note:
In this sample, output will change for every run as we are using shuffle to demonstrate the solution.
The solution will work only as long as array has no duplicate values.
If you do wish to solution to work with arrays with duplicate values, then, one possibility is to look at object_id of array members while figuring out the index.
jumbled_array.map {|i| original_array.map(&:object_id).index(i.object_id)}
This solution will work as long as jumbled_array contains element from original_array and no elements were recreated using dup or something that results in change in object_id values
You can use the map and index methods.
arr = ["a","b","c","d"]
sort_arr = ["d","c","b","a"]
sort_arr.map{|s| arr.index(s)}
# => [3, 2, 1, 0]

Are there accepted names for the two types of arrays in a multidimensional array?

Sorry if this question is a bit elementary, but I was wondering if there are names for the different arrays in a 2D array. For example, in:
int[][] array = new int[5][10];
What do I call the array with the length of 5? And what about the arrays with the length of 10? I was thinking something like the "primary array" and "secondary array" since the secondary arrays are stored in the primary array...
Any thoughts?
When looking at a multidimensional array (an array of arrays), the first length is the amount of rows there are. The second length is the amount of columns. So typically, say if running through a for loop, you could refer to them as such.
An example of a multidimensional array
int [][] arr = new int[2][3] could look like:
[1, 2, 3]
[4, 5, 6]
So there are [2] rows, of [3] columns.

Resources