Perl dynamic hash traversal - perl

A hash of (0 or more levels of hash refs of) array refs of hash refs. Note that the level above the leaf nodes will always be array refs, even if they only have one element.
I need to fetch the aggregate sum of VALUE (in an array of array ref) by preserving the order of the hash refs (In the order of insertion).
Examples :
1)
(
A => {
A1 => [
{ VALUE => 10 },
{ VALUE => 20 }
],
B1 => [
{ VALUE => 30 }
],
},
B => {
A1 => [
{ VALUE => 10 }
],
B1 => [
{ VALUE => 5 }
],
},
C => {
A1 => [
{ VALUE => 100 }
],
},
)
The required output of the above structure will be -
(
[A, A1, 30],
[A, B1, 30],
[B, A1, 10],
[B, B1, 5],
.
.
.
.
)
2)
(
A => [
{ VALUE => 10 },
{ VALUE => 20 }
],
B => [
{ VALUE => 30 }
],
)
The required output of the above structure will be -
(
[A, 30],
[B, 30]
)

You need to write a function that will walk your hash structure and compute the necessary sums. For each key in the hash, it needs to make this decision:
If the value of this key is a list ref, then sum up the VALUE elements in the hashes in this list and return [key, sum]
If the value of this hash is a hash ref, then recurse into that hash. If we got a list back from it, append it to our current output and continue.
At the top level (depth 0), print out each list that's returned.
There are a number of details that still need to be resolved, but that ought to get you started on the right track.

Related

How do I use the forall loop to check if all rows have the same number of columns in a Vector in Scala?

So I have a generic vector: 1:vec: Vector[Vector[T]]
Now I wanna use the require and forall to check if the length of each row is the same.
This is how far I've gotten:
2:require(vec.forall(row => data(row).length == ???)
So essentially I wanna make sure that each row has same number of columns, I don't wanna use 3:data(row + 1).length since I could probably use a for loop in that case. Can anyone give a tip on how to resolve code 2?
If all the rows must have the same length, you can compare each row with any of the others.
if (vec.size < 2) true // vacuous
else {
val firstLength = data(vec.head).length
vec.forall(row => data(row).length == firstLength)
}
Strictly speaking, the first comparison in the forall will always be true, but Vector.tail is probably more work than performing the comparison; if data(row).length is particularly expensive, making it
vec.tail.forall(...)
might be worth it.
(If instead of a Vector, we were dealing with a List, tail is most definitely cheaper than data(row).length, though other cautions around using List may apply)
Consider a 3x4 vector of vectors such as for instance
val xs = Vector.tabulate(3) { _ => Vector.tabulate(4) { _ => 1 }}
namely,
Vector(Vector(1, 1, 1, 1),
Vector(1, 1, 1, 1),
Vector(1, 1, 1, 1))
Collect the size for each nested vector,
val s = xs.map {_.size}
// Vector(4, 4, 4)
Now we can compare consecutive sizes with Vector.forall by pairing them with
s.zip(s.drop(1))
// Vector((4,4), (4,4))
where the first pair corresponds to the first and second vector sizes, and the second pair to the second and third vector sizes; thus
s.zip(s.drop(1)).forall { case(a,b) => a == b }
// true
With this approach we can define other predicates in Vector.forall, such as monotonically increasing pairs,
val xs = Vector(Vector(1), Vector(1,2), Vector(1,2,3))
val s = xs.map {_.size}
// Vector(1, 2, 3)
s.zip(s.drop(1))
// Vector((1,2), (2,3))
s.zip(s.drop(1)).forall { case(a,b) => a == b }
// false
s.zip(s.drop(1)).forall { case(a,b) => a < b }
// true

NetLogo nested list items to character seperated string

I have a triple nested list:
[
[
[a b]
[c d]
...
]
[
[e f]
[g h]
...
]
]
I want a string with the format a,c,... respectively e,g,..
My current approach is to first make a new list with as much items as the first nested list has and add the first items of the lists within said list.
Afterwards then new list is reduced:
let nl ( n-values ( length ( item 0 list) ) [ i -> ( item 0 ( item i ( item 0 list)) ) ] )
reduce [ [a b] -> (word a "," b) ] nl
Is there a better way to do this, as in this approach it is very difficult to maintain the overview of the "denesting" of the list.
Assuming your list looks like:
let a ( list ( list [ "a" "b" ] [ "c" "d" ] ) ( list [ "e" "f" ] [ "g" "h" ] ) )
I'm not sure that this makes it easier to keep track of the denesting, but you could nest a map within another to get the order you want:
print map [ x -> map [ y -> item 0 y ] x ] a
If you want it as a list of strings with commas, I like the csv:to-row primitive from the csv extension:
print map [ x -> csv:to-row map [ y -> item 0 y ] x ] a
Again, not sure that it's more straightforward but it's an alternative approach!
Edit:
As Seth pointed out, map [ y -> item 0 y ] can be replaced with map first- so the modified versions would look like:
print map [ x -> map first x ] a
and
print map [ x -> csv:to-row map first x ] a
Thanks Seth!

Multiply elements of list of lists with each other

I have List of lists List[List[Int] to n] and Lists[Int] are of different size and i want to multiply values all of them between each other.
For List(List(1,2,3), List(4,5), List(6)) it would be
1*4*6, 1*5*6, 2*4*6, 2*5*6, 3*4*6, 3*5*6
and so on and return result as a List of resulting values List[24, 30, 48, 60, 72, 90]
You can do it using foldLeft this way:
list.foldLeft(List(1)) {
case (acc, item) => acc.flatMap(v => item.map(_*v))
}
Explanation
Lets define method producing all possible multiplication of pairs of two lists:
def mul(a:List[Int], b:List[Int]) = b.flatMap (item => a.map(_*item))
this method for each item in b produces a list of items from a multiplied by current value of b
Now we can apply this procedure to all elements of list of lists, giving it initial value of List(1)

How to create a hash of arrays or hash of hashes

I have a file named Jobs.conf which contains:
JobName: A
JobSize: 100
JobArrival:1
JobExe:100
JobName: B
JobSize: 100
JobArrival:2
JobExe:100
JobName: C
JobSize: 100
JobArrival:3
JobExe:100
JobName: D
JobSize: 100
JobArrival:4
JobExe:100
Is it possible to read this file so each Job is stored in an array and then the 4 arrays are stored in a hash? Would it make more sense to store this as a hash of hashes and is that possible?
The key is to set $/ (the input record separator) properly:
This influences Perl's idea of what a "line" is. Works like awk's RS
variable, including treating empty lines as a terminator if set to the
null string (an empty line cannot contain any spaces or tabs). You may
set it to a multi-character string to match a multi-character
terminator, or to undef to read through the end of file. Setting it
to "\n\n" means something slightly different than setting to "",
if the file contains consecutive empty lines. Setting to "" will
treat two or more consecutive empty lines as a single empty line.
Setting to "\n\n" will blindly assume that the next input character
belongs to the next paragraph, even if it's a newline.
Then we just take advantage of how the records are laid out by split-ing directly into a hash reference:
use strict;
use warnings;
use Data::Dump;
local $/ = "";
my #jobs;
while (<DATA>) {
push(#jobs, {split(/:\s*|\n/)});
}
dd(\#jobs);
__DATA__
JobName: A
JobSize: 100
JobArrival:1
JobExe:100
JobName: B
JobSize: 100
JobArrival:2
JobExe:100
JobName: C
JobSize: 100
JobArrival:3
JobExe:100
JobName: D
JobSize: 100
JobArrival:4
JobExe:100
Or just:
my #jobs = map { {split(/:\s*|\n/)} } <DATA>;
Output:
[
{ JobArrival => 1, JobExe => 100, JobName => "A", JobSize => 100 },
{ JobArrival => 2, JobExe => 100, JobName => "B", JobSize => 100 },
{ JobArrival => 3, JobExe => 100, JobName => "C", JobSize => 100 },
{ JobArrival => 4, JobExe => 100, JobName => "D", JobSize => 100 },
]
An array of hashes (the previous example) would be my preference, but if you wanted a hash of hashes, you'd need to modify the code slightly:
my %jobs;
while (<DATA>) {
my %temp = split(/:\s*|\n/);
$jobs{delete($temp{JobName})} = \%temp;
}
dd(\%jobs);
Output:
{
A => { JobArrival => 1, JobExe => 100, JobSize => 100 },
B => { JobArrival => 2, JobExe => 100, JobSize => 100 },
C => { JobArrival => 3, JobExe => 100, JobSize => 100 },
D => { JobArrival => 4, JobExe => 100, JobSize => 100 },
}

why do they want to save a hash in an array?

I saw a very strange piece of code in a perl script used in my project, it's something like:
my $arrayRef = [
A => {AA => 11, AAA => 111},
B => {BB => 11, BBB => 111},
];
IMO, it tries to construct an anonymous array from a hash table. I try to print the array element and here is what I get:
foreach (#$arrayRef )
{
print;
print "\n";
}
A
HASH(0x1e60220)
B
HASH(0x1e71bd0)
which means it treats every element (key&value) in the hash table as a separate element in the anonymous array. However I am really confused about why do they want to save a hash into an array. The ONLY benefit for me is to save some memory if the hash table is really huge. Is this a wedely used perl tricks?
Thanks!
it tries to construct an anonymous array from a hash table.
No, it constructs an anonymous array from a four-element list.
A => {AA => 11, AAA => 111}, B => {BB => 11, BBB => 111}
is exactly the same thing as
'A', {AA => 11, AAA => 111}, 'B', {BB => 11, BBB => 111}
The use of => does imply some sort of relationship, so I suppose they could have used
{ A => {AA => 11, AAA => 111}, B => {BB => 11, BBB => 111} }
or
[ [ A => {AA => 11, AAA => 111} ], [ B => {BB => 11, BBB => 111} ] ]
or any of a million other data structures, but there's way to know why one was chosen over another from what you gave.
It's an anonymous array, in which alternates a string key with an anonymous hash. The answer to your question: it depends on context, a concrete data-structure should help to resolve a concrete problem. So if we have only the data-structure and forget the problem we are trying to resolve, it's harder to imagine why they used this construction.
Perhaps, they needed a "ordered hash of hashes", the array structure makes sure the order, hash not