hash holding the values of address of a 2 D array - arrays

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.

Related

Infinitely expanding array

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"]]

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

How to find the key of a hash whose value has the most elements

I'm using Ruby 2.4.
I have a hash whose key is a number and whose value is an array of elements. How do I find the key in the hash with the value that has the most elements? I know that if my value were a single number I could do this:
my_hash.max_by { |k, v| v }
But since the value is an array, I'm not sure how to tell the above to use the number of elements in the array as what should be maxed.
max_by is the correct method :
my_hash = { a: [1, 2], b: [1, 2, 3], c: [5] }
key, longest_array = my_hash.max_by{ |k, array| array.size }
p key
#=> :b
p longest_array
#=> [1, 2, 3]
You just need to specify on which object the comparison should be. In this case, the size of the array value.
You might need to add some checks first : this will only work if all the hash values respond to :size.
You can do it like this:
my_hash.map {|k, v| [k, v.count]}.max_by {|k, v| v}.first
The first map will return an array of two elements arrays. For each of them, the first element is the key and the second is the number of elements of the corresponding array. Then it uses max_by to return the two element array with the maximum number of elements. Finally, the first method returns the key.
I'm not sure if I understood your question correctly, but I'm assuming you have something like this:
my_hash = {1=>[2, 1, 3, 4], 2=>[1, 2], 3=>[1, 4, 6]}
If that's the case, you can get the key for the largest array like this:
my_hash.max_by{|k,v| v.count}.first

Neo4j Cypher - Collect two array values return one object

I have multiple nodes with same label. The node properties have two arrays. I want join both array values to an object or a map.
Example:
Array one: [1,2,3,4,5]
Array two: [5,4,3,2,1]
I want to return result as {output:[{1,5},{2,4},{3,3},{4,2},{5,1}]} so a total of 5 objects in that output result.
Is this possible in Cypher?
WITH [1,2,3,4,5] AS array_one, [5,4,3,2,1] AS array_two
UNWIND RANGE(0, SIZE(array_one) - 1) AS i
WITH [array_one[i], array_two[i]] AS output
WITH COLLECT(output) AS output_list
RETURN {outputs: output_list}
That will give you a map, whose sole value is a list of lists. If you want to dynamically build a list of maps instead (your question's syntax is ambiguous), you will have to look into apoc, Cypher doesn't natively support dynamic key assignment.
APOC procedures may be the way to go on this one. In the Collection Functions section, the procedure you want is apoc.coll.zip([list1],[list2]). It is similar to what you want, but not exact. Rather than returning a list of objects, it will return a list of list pairs:
with [1,2,3,4,5] as list1, [5,4,3,2,1] as list2
call apoc.coll.zip(list1,list2) yield value
return {outputs:value}
// returns {outputs:[[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]}
Regarding your desired output, objects in Cypher are like JSON objects and consist of key/value pairs, so it is impossible to return it in the format you're describing. You can test this for yourself.
// this works just fine
return {output: [[1,2]]}
// this causes a syntax error
return {output: [{1,2}]}
Array of maps
You can generate a map containing an array of maps without using APOC:
WITH [1,2,3,4,5] AS a1, [5,4,3,2,1] AS a2
RETURN {output: REDUCE(s = [], i IN RANGE(0, SIZE(a1)-1) | s + {one: a1[i], two: a2[i]})} AS res;
The output is:
{output:[{"one":1,"two":5},{"one":2,"two":4},{"one":3,"two":3},{"one":4,"two":2},{"one":5,"two":1}]}
Array of arrays
To generate a map containing an array of arrays:
WITH [1,2,3,4,5] AS a1, [5,4,3,2,1] AS a2
RETURN {output: REDUCE(s = [], i IN RANGE(0, SIZE(a1)-1) | s + [[a1[i], a2[i]]])} AS res;
The output is:
{output:[[1,5],[2,4],[3,3],[4,2],[5,1]]}

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]

Resources