Lets take 2 arrays arr1 = ['a', 'b', 'c'] and arr2 = ['1' , '2', '3']. When passed these arrays as params to a soy template, I want to iterate as shown below and print an index that indicates total items iterated so far.
index: 0 //variable assigned to 0 by default
{foreach $i in $arr1}
{foreach $j in $arr2}
index = index + 1; //variable incremented by 1
{$index} th item //print item index
{/foreach}
{/foreach}
Since variable declared using let cannot be re-assigned to a new value, is there a way in templates to achieve the logic I have shown above.
Within the block, you can use three special functions that only take the iterator as their argument:
isFirst($var) returns true only on the first iteration.
isLast($var) returns true only on the last iteration.
index($var) returns the current index in the list. List indices are 0-based.
Then you can use index($j):
{foreach $i in $arr1}
{foreach $j in $arr2}
{index($j)}
{/foreach}
{/foreach}
Hope I could help ;)
Source: https://developers.google.com/closure/templates/docs/commands#foreach
Related
The thing that I want to do is to compare the two arrays, find out if any duplication has been made in the second array versus the first array. Then if there has been any duplication, remove it from the second array so that if they select the same value in both lists that it will only be in the first.
first array (1,2,3,6,7.9)
second array (4,5,6,9,10,11)
results would be
first array (1,2,3,6,7,9)
second array (4,5,10,11)
$first = array (1,2,3,6,7,9);
$second = array (4,5,10,11);
foreach ($second as $k=>$v){
if(in_array($v, $first)){
unset($second[$k]);
}
}
$second = array_values($second);
print_r($second); //Output
If I use an each do loop to fill an array, it will leave the array as it is (in this case it will be a nil array of size 4)
array = Array.new(4)
array.each do |i|
i = 5
end
I understand that I can initialize an array with my desired value using array = Array.new(4) {desired value} but there are situations in which I'm choosing between different values and I am trying to understand how the each do loop work exactly.
The current way I'm doing it is the following which fills in the array with my desired value
array = Array.new(4)
array.each_with_index do |val, i|
array[i] = 5
end
Solution
You need :
array = Array.new(4) do |i|
5
# or some logic depending on i (the index between 0 and 3)
end
Your code
array = Array.new(4)
array is now an Array with 4 elements (nil each time).
array.each iterates over those 4 elements (still nil), and sets i as block-local variable equal to nil.
Inside this block, you override i with 5, but you don't do anything with it. During the next iteration, i is set back to nil, and to 5, and so on...
You don't change the original array, you only change local variables that have been set equal to the array elements.
The difference is that
i = 5
is an assignment. It assigns the value 5 to the variable i.
In Ruby, assignments only affect the local scope, they don't change the variable in the caller's scope:
def change(i)
i = 5 # <- doesn't work as you might expect
end
x = nil
change(x)
x #=> nil
It is therefore impossible to replace an array element with another object by assigning to a variable.
On the other hand,
array[i] = 5
is not an assignment, but a disguised method invocation. It's equivalent to:
array.[]=(i, 5)
or
array.public_send(:[]=, i, 5)
It asks the array to set the element at index i to 5.
An easy one for a Perl guru...
I want a function that simply takes in an array of items (actually multiple arrays) and counts the number of times each item in the key section of a hash is there. However, I am really unsure of Perl hashes.
#array = qw/banana apple orange apple orange apple pear/
I read that you need to do arrays using code like this:
my %hash = (
'banana' => 0,
'orange' => 0,
'apple' => 0
#I intentionally left out pear... I only want the values in the array...
);
However, I am struggling getting a loop to work that can go through and add one to the value with a corresponding key equal to a value in the array for each item in the array.
foreach $fruit (#array) {
if ($_ #is equal to a key in the hash) {
#Add one to the corresponding value
}
}
This has a few basic functions all wrapped up in one, so on behalf of all beginning Perl programmers, thank you in advance!
All you need is
my #array = qw/banana apple orange apple orange apple pear/;
my %counts;
++$counts{$_} for #array;
This results in a hash like
my %counts = ( apple => 3, banana => 1, orange => 2, pear => 1 )
The for loop can be written with block and a an explicit loop counter variable if you prefer, like this
for my $word (#array) {
++$counts{$word};
}
with exactly the same effect.
You can use exists.
http://perldoc.perl.org/functions/exists.html
Given an expression that specifies an element of a hash, returns true
if the specified element in the hash has ever been initialized, even
if the corresponding value is undefined.
foreach my $fruit (#array) {
if (exists $hash{$fruit}) {
$hash{$fruit}++;
}
}
Suppose you have an array named #array. You'd access the 0th element of the array with $array[0].
Hashes are similar. %hash's banana element can be accessed with $hash{'banana'}.
Here's a pretty simple example. It makes use of the implicit variable $_ and a little bit of string interpolation:
use strict;
my #array = qw/banana apple orange apple orange apple pear/;
my %hash;
$hash{$_} += 1 for #array; #add one for each fruit in the list
print "$_: $hash{$_}\n" for keys %hash; #print our results
If needed, you can check if a particular hash key exists: if (exists $hash{'banana'}) {...}.
You'll eventually get to see something called a "hashref", which is not a hash but a reference to a hash. In that case, $hashref has $hashref->{'banana'}.
I'm trying to understand you here:
You have an array and a hash.
You want to count the items in the array and see how many time they occur
But, only if this item is in your hash.
Think of hashes as keyed arrays. Arrays have a position. You can talk about the 0th element, or the 5th element. There is only one 0th element and their is only one 5th element.
Let's look at a hash:
my %jobs;
$jobs{bob} = "banker";
$jobs{sue} = "banker";
$jobs{joe} = "plumber;
Just as we can talk about the element in the array in the 0th position, we can talk about the element with the of bob. Just as there is only one element in the 0th position, there can only be one element with a key of bob.
Hashes provide a quick way to look up information. For example, I can quickly find out Sue's job:
print "Sue is a $jobs{sue}\n";
We have:
An array filled with items.
A hash with the items we want to count
Another hash with the totals.
Here's the code:
use strict;
use warnings;
use feature qw(say);
my #items = qw(.....); # Items we want to count
my %valid_items = (....); # The valid items we want
# Initializing the totals. Explained below...
my %totals;
map { $totals{$_} = 0; } keys %valid_items;
for my $item ( #items ) {
if ( exists $valid_items{$item} ) {
$totals{$item} += 1; #Add one to the total number of items
}
}
#
# Now print the totals
#
for my $item ( sort keys %totals ) {
printf "%-10.10s %4d\n", $item, $totals{$item};
}
The map command takes the list of items on the right side (in our case keys %valid_items), and loop through the entire list.
Thus:
map { $totals{$_} = 0; } keys %valid_items;
Is a short way of saying:
for ( keys %valid_items ) {
$totals{$_} = 0;
}
The other things I use are keys which returns as an array (okay list) all of the keys of my hash. Thus, I get back apple, banana, and oranges when I say keys %valid_items.
The [exists](http://perldoc.perl.org/functions/exists.html) is a test to see if a particular key is in my hash. The value of that key might be zero, a null string, or even an undefined value, but if the key is in my hash, theexists` function will return a true value.
However, if we can use exists to see if a key is in my %valid_items hash, we could do the same with %totals. They have the same set of keys.
Instead or creating a %valid_items hash, I'm going to use a #valid_items array because arrays are easier to initialize than hashes. I just have to list the values. Instead of using keys %valid_items to get a list of the keys, I can use #valid_items:
use strict;
use warnings;
use feature qw(say);
my #items = qw(banana apple orange apple orange apple pear); # Items we want to count
my #valid_items = qw(banana apple orange); # The valid items we want
my %totals;
map { $totals{$_} = 0; } #valid_items;
# Now %totals is storing our totals and is the list of valid items
for my $item ( #items ) {
if ( exists $totals{$item} ) {
$totals{$item} += 1; #Add one to the total number of items
}
}
#
# Now print the totals
#
for my $item ( sort keys %totals ) {
printf "%-10.10s %4d\n", $item, $totals{$item};
}
And this prints out:
apple 3
banana 1
orange 2
I like using printf for keeping tables nice and orderly.
This will be easier to understand as I too started to write code just 2 months back.
use Data::Dumper;
use strict;
use warnings;
my #array = qw/banana apple orange apple orange apple pear/;
my %hashvar;
foreach my $element (#array) {
#Check whether the element is already added into hash ; if yes increment; else add.
if (defined $hashvar{$element}) {
$hashvar{$element}++;
}
else {
$hashvar{$element} = 1;
}
}
print Dumper(\%hashvar);
Will print out the output as
$VAR1 = {
'banana' => 1,
'apple' => 3,
'orange' => 2,
'pear' => 1
};
Cheers
I'm stuck.
I would like to create a multidim array with the following structure
$x[index]['word']="house"
$x[index]['number']=2,5,7,1,9
where index is the first dimension from 0 to... n
second dimension has two fields "word" and "number"
and each of these two fields holds an array (the first with strings, the second with numbers)
I do not know how to declare this $x
I've tried with
$x = #(()),#(#()) - doesn't work
or
$x= ("word", "number"), #(#()) - doesn't work either
or
$x = #(#(#(#()))) - nope
Then I want to use this array like this:
$x[0]["word"]= "bla bla bla"
$x[0]["number]= "12301230123"
$x[1]["word"]= "lorem ipsum"
$x[2]["number]=...
$x[3]...
$x[4]...
The most frequent errors are
Array assignment failed because index '0' was out of range.
Unable to index into an object of type System.Char/INt32
I would like to accomplish this using arrays[][] or jaws # but no .net [,] stuff.
I think I'm missing something.
If I understood you correctly, you're looking for an array of hashtables. You can store whatever you want inside an object-array, so store hashtables that you can search with words or numbers as keys. Ex:
$ht1 = #{}
$ht1["myword"] = 2
$ht1["23"] = "myvalue"
$ht2 = #{}
$ht2["1"] = 12301230123
$arr = #($ht1,$ht2)
PS > $arr[1]["1"]
12301230123
PS > $arr[0]["myword"]
2
PS > $arr[0]["23"]
myvalue
If you know how many you need, you can use a shortcut to create it:
#Create array of 100 elements and initialize with hashtables
$a = [object[]](1..100)
0..($a.Length-1) | % { $a[$_] = #{ 'word' = $null; 'number' = $null } }
#Now you have an array of 100 hastables with the keys initialized. It's ready to recieve some values.
PS > $a[99]
Name Value
---- -----
number
word
And if you need to add another pair later, you can simply use:
$a += #{ 'word' = $yourwordvar; 'number' = $yournumbervar }
You could make an array, and initialize it with hashtables:
$x=#(#{})*100;
0..99 | foreach {$x[$_]=#{}};
$x[19]["word"]="house";
$x[19]["number"]=25719;
You want a big array, for example of length 100. Note the difference in parentheses!
You need the second step, because in the previous command the pointer of the hashtable was copied 100 times... and you don't want that :)
Now test it:
$x[19]["number"];
25719
$[19]["word"];
house
If say I have an array and I would to iterate through the array, but do something different to the first and last element. How should I do that?
Taking the below code as example, how do I alert element a and e?
array = [a,b,c,d,e]
for element in array
console.log(element)
Thanks.
You can retrieve the first and last elements by using array destructuring with a splat:
[first, ..., last] = array
This splat usage is supported in CoffeeScript >= 1.7.0.
The vanilla way of accessing the first and last element of an array is the same as in JS really: using the index 0 and length - 1:
console.log array[0], array[array.length - 1]
CoffeeScript lets you write some nice array destructuring expressions:
[first, mid..., last] = array
console.log first, last
But i don't think it's worth it if you're not going to use the middle elements.
Underscore.js has some helper first and last methods that can make this more English-like (i don't want to use the phrase "self-explanatory" as i think any programmer would understand array indexing). They are easy to add to the Array objects if you don't want to use Underscore and you don't mind polluting the global namespace (this is what other libraries, like Sugar.js, do):
Array::first ?= (n) ->
if n? then #[0...(Math.max 0, n)] else #[0]
Array::last ?= (n) ->
if n? then #[(Math.max #length - n, 0)...] else #[#length - 1]
console.log array.first(), array.last()
Update
This functions also allow you to get the n first or last elements in an array. If you don't need that functionality then the implementation would be much simpler (just the else branch basically).
Update 2
CoffeeScript >= 1.7 lets you write:
[first, ..., last] = array
without generating an unnecessary array with the middle elements :D
The shortest way is here
array[-1..]
See this thread
https://github.com/jashkenas/coffee-script/issues/156
You can use just:
[..., last] = array
You can use slice to get last element. In javascript, slice can pass negative number like -1 as arguments.
For example:
array = [1, 2, 3 ]
console.log "first: #{array[0]}"
console.log "last: #{array[-1..][0]}"
be compiled into
var array;
array = [1, 2, 3];
console.log("first: " + array[0]);
console.log("last: " + array.slice(-1)[0]);
You can get the element and the index of the current element when iterating through the array using Coffeescript's for...in. See the following code, replace the special_process_for_element and normal_process_for_element with your code.
array = [a, b, c, d]
FIRST_INDEX = 0
LAST_INDEX = array.length - 1
for element, index in array
switch index
when FIRST_INDEX, LAST_INDEX
special_process_for_element
else
normal_process_for_element
sample
Here's a working code