How would I go about creating an array of arrays, that can continue that way, adding arrays inside arrays etc, without explicitly knowing how many arrays can contain arrays?
On top of this, out of curiosity, is it possible to change type in place with Arrays, for example if I create an array with ["test"] can I subsequently change it to [["test"]] and so on?
Any comprehensive tutorials on how arrays can be nested etc would be amazing, but currently it's still very difficult to search for crystal topics.
You can use recursive aliases for this (see language reference for alias):
alias NestedArray = Array(NestedArray) | <YourArrayItemType(s)>
An example (carc.in):
alias NestedArray = Array(NestedArray) | Int32
array = [] of NestedArray
array << 1
array << [2, 3, 4, [5, [6, 7, [8] of NestedArray] of NestedArray] of NestedArray] of NestedArray
array << Array(NestedArray){Array(NestedArray){10, 11}}
array # => [1, [2, 3, 4, [5, [6, 7, [8]]]], [[10, 11]]]
Concerning the second question, I am not sure what you mean. You can change the type of a variable like this:
array = ["test"]
array = [array]
array # => [["test"]]
Related
I have a nested array:
arr = [[1,nil,2,3,4], [2,nil,4,5,6], [6,nil,3,3,5]]
Any elements at the same index in the subarrays that are nil across the array must be removed. The second index in all subarrays have nil.
I did this:
collection = arr.transpose.select(&:any?).transpose
# => [[1, 2, 3, 4], [2, 4, 5, 6], [6, 3, 3, 5]]
It works for me, albiet I am using transpose twice. Could this technique lead to data getting mixed up? It looks fool proof to me.
With the nil-vs-false caveat that #CarySwoveland noted in a comment, yes, your double-transpose is safe: it will only work on data that's rectangular to begin with, and it will produce equally-rectangular data as output. You're filtering out whole rows, so nothing can get misaligned.
While it's not super efficient, it's not too bad, and is far more expressive & readable than more direct looping & manipulation.
This question is different from this one.
I have an array of arrays of AR items looking something like:
[[1,2,3], [4,5,6], [7,8,9], [7,8,9], [1,2,3], [7,8,9]]
I would like to sort it by number of same occurences of the second array:
[[7,8,9], [1,2,3], [4,5,6]]
My real data are more complexes, looking something like:
raw_data = {}
raw_data[:grapers] = []
suggested_data = {}
suggested_data[:grapers] = []
varietals = []
similar_vintage.varietals.each do |varietal|
# sub_array
varietals << Graper.new(:name => varietal.grape.name, :grape_id => varietal.grape_id, :percent => varietal.percent)
end
raw_data[:grapers] << varietals
So, I want to sort raw_data[:grapers] by the max occurrencies of each varietals array comparing this value: grape_id inside them.
When I need to sort a classical array of data by max occurencies I do that:
grapers_with_frequency = raw_data[:grapers].inject(Hash.new(0)) { |h,v| h[v] += 1; h }
suggested_data[:grapers] << raw_data[:grapers].max_by { |v| grapers_with_frequency[v] }
This code doesn't work cos there are sub arrays there, including AR models that I need to analyze.
Possible solution:
array.group_by(&:itself) # grouping
.sort_by {|k, v| -v.size } # sorting
.map(&:first) # optional step, depends on your real data
#=> [[7, 8, 9], [1, 2, 3], [4, 5, 6]]
I recommend you take a look at the Ruby documentation for the sort_by method. It allows you to sort an array using anything associated with the elements, rather than the values of the elements.
my_array.sort_by { |elem| -my_array.count(elem) }.uniq
=> [[7, 8, 9], [1, 2, 3], [4, 5, 6]]
This example sorts by the count of each element in the original array. This is preceded with a minus so that the elements with the highest count are first. The uniq is to only have one instance of each element in the final result.
You can include anything you like in the sort_by block.
As Ilya has pointed out, having my_array.count(elem) in each iteration will be costlier than using group_by beforehand. This may or may not be an issue for you.
arr = [[1,2,3], [4,5,6], [7,8,9], [7,8,9], [1,2,3], [7,8,9]]
arr.each_with_object(Hash.new(0)) { |a,h| h[a] += 1 }.
sort_by(&:last).
reverse.
map(&:first)
#=> [[7.8.9]. [1,2,3], [4,5,6]]
This uses the form of Hash::new that takes an argument (here 0) that is the hash's default value.
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
Consider following arrays:
array1 = ['a','b'];
array2 = ['a','b','c','d'];
I need to extract the difference. So my resulting array should look something like,
array3 = ['c','d'];
If an element is present in array1 then it should be poped from array2.
I am looking for solutions more angular way,is there any directive available?
In my opinion you can use underscore or lodash library for such tasks.
for example in underscore you can done it through this simple code :
difference_.difference(array, *others)
Similar to without, but returns the values from array that are not present in the other arrays.
_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]
underscore annotated source
In Perl, how can I create a hash, whose values will be the address of a 2D array?
I need to get the values of the 2D array dynamically, too.
Please give me the exact coding. I am breaking my head.
How about this?
my %hash = (
foo => [[1, 2], [3, 4]],
bar => [[5, 6], [7, 8]]
);
2D array is modelled as array of arrays here.
Arrays and hashes can only take scalar values, however an array reference (created using [], among other ways) are scalars. Therefore creating nested arrays is done using this construct. Think of it as:
$array_element_1 = ['row 1 column 1', 'row 1 column 2'];
$array_element_2 = ['row 2 column 1', 'row 2 column 2'];
$array_reference = [$array_element_1, $array_element_2];
%hash = ( 'key' => $array_reference);
except without all of the intermediate storing. These are called anonymous references (since they don't require that you give the original structure a name before creating the reference to the structure). Note that anonymous hash references are created using {}. Read more at perldoc perlreftut.