Create and iterate through an array in Velocity Template Language - vtl

How to create an array in VTL and add contents to the array? Also how to retrieve the contents of the array by index?

According to Apache Velocity User Guide, right hand side of assignments can be of type
Variable reference
List item
String literal
Property reference
Method reference
Number literal
ArrayList
Map
You can create an empty list, which would satisfy all your needs for an array, in an Apache Velocity template with an expression like:
#set($foo = [])
or initialize values:
#set($foo = [42, "a string", 21, $myVar])
then, add elements using the Java add method:
$foo.add(53);
$foo.add("another string");
but beware, as the Java .add() method for the list type returns a boolean value, when you add an element to the list, Velocity will print, for instance, "true" or "false" based on the result of the "add" function.
A simple work around is assigning the result of the add function to a variable:
#set($bar = $foo.add(42))
You can access the elements of the list using index numbers:
<span>$foo[1]</span>
Expression above would show a span with the text "a string". However the safest way to access elements of a list is using foreach loops.

Creating an array is easy:
#set($array = [])
Putting an element into an array is also easy:
$array.add(23)
Getting an element from an array depends from your Velocity version.
In Velocity 1.6 you must use
$array.get($index)
Since Velocity 1.7 you can use the classic form:
$array[$index]

I haven't created an array in VTL but passed arrays to VTL context and used them. In VTL, you can not retrieve array contents by index, you only use foreach, as example this code is copied from my Dynamic SQL generation VTL Script:
#foreach( $col in $Columns ) SUM($col.DBColumn) AS ''$col.Name''#if($velocityCount!=$Columns.Count), #end #end
For this reason, we also can not have 2D arrays. When I needed an array to store 2 objects in a row, I used the workaround of defining a new class, and putting objects of that class in the single dimensional array.

Related

I have an array a=[1,2,3,4,5,6] and in next line i want array that has only even values in it. Trying to do this by .collect but value is in boolean

a=[1,2,3,4,5,6,7,8]
w=a.collect{|i| i%2==0}
p w
The result is coming to be
[false,true,false,true]
why?
When i am doing
w=a.collect{|i| i+2}
Result is an array like
[3,4,5,6,7,8,9,10,11]
Why? What am i doing wrong?
You don't need map / collect (they are aliases), you need
array.select(&:even?)
or
array.reject(&:odd?)
These methods filter original array, unlike map that performs actions with every element and returns new array of the same length
That's why you get boolean array same length instead of filtering
Please read more in docs:
Array#map, Array#select, Array#reject

Higher order function sort() used it with other higher order function its working with let content also

So, any reason behind happen this things, because when i perform sort() function with let type at that time xcode give me a compile time error
i tried it in my playgound with only sort function and sort() function with other higher order function.
like so
let name = ["mehul","HeLLi","JeniFER","Ankul"]
name.sort()
error :
Cannot use mutating member on immutable value: 'name' is a 'let' constant
but with other higher order functions
let nameStartingWithBArray = name.filter {$0.first != "B"}.map {$0.uppercased()}.sorted()
now there is no error
Please consider the subtle but crucial difference between sort and sorted
sort has no return value. It sorts in place that means the calling object is mutated.
sorted ( as well as filter and map) returns a new object with the result of the operation.
sort() basically works with the list itself. It modifies the original list in place. The return value is None.
name.sort() sorts the list and save the sorted list.
sorted() works on any iterable that may include list, dict and so on. It returns another list and doesn't modify the original list.
sorted() returns a sorted copy of the list (a new sorted list), without changing the original list.
Keynote : sort() is faster than sorted()
The sort function sorts the collection in place - i.e. it modifies the array, name, on which you call sort.
filter on the other hand returns an array and does not modify the original array.
Compare sort with sorted which again returns a new array and does not modify the original array.
So, you can write
let sortedNames = name.sorted()
sortedNames will be in order, while name will be in the original, unsorted, order.
If you write
var name = ["mehul","HeLLi","JeniFER","Ankul"]
name.sort()
then name will be in order, and because it is declared as var rather than a constant with let the change is permitted.
The sort func you are using is the mutating func, that means sort function internally sort the array in the same variable.
Mutating Func : To modify the properties of your structure or enumeration within a particular method, you can opt in to mutating behavior for that method. The method can then mutate (that is, change) its properties from within the method, and any changes that it makes are written back to the original structure when the method ends.
So. let doesn't allow sort for doing mutating, so you need to make it var.
More ever, if you use sorted(by:) , it returns new array of sorted values. So here you don't get any error.

programatically making a 2d array in swift

I need to use a for loop to create a 2d array. So far "+=" and .append have not yielded any results. Here is my code. Please excuse the rushed variable naming.
let firstThing = contentsOfFile!.componentsSeparatedByString("\n")
var secondThing: [AnyObject] = []
for i in firstThing {
let temp = i.componentsSeparatedByString("\"")
secondThing.append(temp)
}
The idea is that it takes the contents of a csv file, then separates the individual lines. It then tries to separate each of the lines by quotation marks. This is where the problem arises. I am successfully making the quotation separated array (stored in temp), however, I cannot make a collection of these in one array (i.e. a 2d array) using the for loop. The above code generates an error. Does anybody have the answer of how to construct this 2d array?
You can do this using higher order functions...
let twoDimensionalArray = contentsOfFile!.componentsSeparatedByString("\n").map{
$0.componentsSeparatedByString("\"")
}
The map function takes an array of items and maps each one to another type. In this I'm mapping the strings from the first array into an array pf strings and so creating a 2d array.
This will infer the type of array that is created so no need to put [[String]].
Here you go...

XPages repeat from array value field

I have a field which value is an array of strings.
Example: Mom, dad, son, etc.
It is possible to repeat a link with those values?
Example:
Mom
dad
son
And when I click on the link to have a href=www."fieldvalue".com.
EDIT: it is not vector, it is Array.
Create your repeat control. For the value add in your field name. Something like :
document1.getItemValue("myMultiValueField")
I THINK that should repeat your field assuming it is a real multi-value. The comma deliminated string would require more work. So I'm not talking about that...
Make sure the collection name / var name of the repeat is something like "rowData"
rowData should then be a String.
Drop a link control inside the repeat.
Compute the label to be simple "rowData". (no quotes in the code)
Compute the URL - which I THINK is "value" in all properties of the link
That's just javaScript so you should be able to do something like:
return "http://" + rowData + ".com"
That's rough - you'll have to play with it but if I follow you correctly should work.
For a comma deliminated String... in the repeat control you'd need to use SSJS or #functions to break that into an array so the repeat can work on it.
In your repeat you'll need to map the value attribute to the Vector and set a var property, which is how you will reference each element. Note: a comma-separated string is a single value, and a repeat requires multiple values. So you'll need to convert it to a Vector or some other multi-value object.
Within the repeat you can use any other control and compute the value as you would elsewhere. To access each element in your repeat control's source (i.e. each String in your Vector, in this case), use the variable name you've defined in the var property.

Linked List without using pointers and struct

How to implement linked list in C/C++ with out using
struct node{
int data;
struct node *next;
}
just using two arrays, one for data, other for next node
Sure you can. There is some discussion about the topic here: Is a Linked-List implementation without using pointers possible or not?
One implementation would be to create an array, and store the nodes in the array. Wikipedia has a good pseudo-code example: http://en.wikipedia.org/wiki/Linked_list (Linked lists using arrays of nodes section)
You define two arrays
1.Data Array
2.Index Array
every data array will contain data value and corresponding index in Index array will contain next node to be pointed by the value element
you need to keep track of the last value added because it gives the index of Index array where you can add an index of the next value pointed by that value node.
Adding a data value is also easy just add a new value in the data array and
fill the previous element value in Index array by the index of the data value in data element.
Data Array 2,5,3,1,2.
Index Array 1,2,3,4,0 (0 means it is not pointing to any data element)
add element: 2,5,3,1,2,77.
Index Array 1,2,3,4,5,0.
delete element: 2,5,0,1,2,77
Index Array 1,3,0,4,5,0.

Resources