last entry in a loop - smarty

I have an associative array and I generate a lot of different things with this array.
The output I need has the form
aa, ab, ac, ad, af, ak, az
So the last entry does not have a comma after it
{section name=i loop=$aColums}
{if $aColums[i].contshow eq 'y'}
{$aColums[i].Name}
{endif}
{/section}
My problem is that I don't know when I've reached the last value, which has the contshow=y attribute. So my next thought was to apply the comma before I write aColums[i].Name. But here I have a similar problem becuase I don't know when I've reached the first value with contshow=y.
Does anyone have a suggestion?

There is an alternative method, using the section's .last property.
{section name=i loop=$aColums}
{if $aColums[i].contshow eq 'y'}
{$aColums[i].Name}{if $smarty.section.i.last eq false}, {/if}
{endif}
{/section}
This adds a ', ' after every output Name - unless it's the last iteration of the {section}. I'm assuming that your $aColums array data doesn't already have commas tacked on.
You also have another option - pregenerate this string in PHP using implode:
$aColumsString = implode(', ', $aColums);
$smarty->assign('aColumsString', $aColumsString);
Then just output to the template as needed. If you require the list with commas more than once, this is probably the more efficient method. If you need it once, it's probably a toss-up effiency-wise.

The general way to deal with this is to write the commas before each element. In this way, the special-case is the first element (which doesn't need a preceding comma) rather than the last, and it's a lot easier to work out whether you're seeing the first element or not. Just set a boolean flag to true initially, then set it to false after matching an entry.
Mind you, Smarty might have a utility function for "joining" the array with a given string (comma, in this case). If such a function exists, using it directly would be the best option.

In Smarty 3, this is much simplified:
{foreach $aColumns AS $aCol}
{$aCol}{if not $aCol#last}, {/if}
{/foreach}

Related

How to use gsubstitution with more letters

I've printed the code, wit ruby
string = "hahahah"
pring string.gsub("a","b")
How do I add more letter replacements into gsub?
string.gsub("a","b")("h","l") and string.gsub("a","b";"h","l")
didnt work...
*update I have tried this too but without any success .
letters = {
"a" => "l"
"b" => "n"
...
"z" => "f"
}
string = "hahahah"
print string.gsub(\/w\,letters)
You're overcomplicating. As with most method calls in Ruby, you can simply chain #gsub calls together, one after the other:
str = 'adfh'
print str.gsub("a","b").gsub("h","l") #=> 'bdfl'
What you're doing here is applying the second #gsub to the result of the first one.
Of course, that gets a bit long-winded if you do too many of them. So, when you find yourself stringing too many together, you'll want to look for a regex solution. Rubular is a great place to tinker with them.
The way to use your hash trick with #gsub and a regex expression is to provide a hash for all possible matches. This has the same result as the two #gsub calls:
print str.gsub(/[ah]/, {'a'=>'b', 'h'=>'l'}) #=> 'bdfl'
The regex matches either a or h (/[ah]/), and the hash is saying what to substitute for each of them.
All that said, str.tr('ah', 'bl') is the simplest way to solve your problem as specified, as some commenters have mentioned, so long as you are working with single letters. If you need to work with two or more characters per substitution, you'll need to use #gsub.

How to eliminate multiple instances of a substring from a string

I got a string
str = "<strong><strong>HI</strong></strong>".
I want to eliminate duplicate instances of <strong> and </strong> to get <strong>HI</strong>.
There could potentially be more than two instances.
I tried to use squeeze('<strong>'), but it doesn't seem to do the job.
you could do this:
str = "<strong><strong>HI</strong></strong>"
str.gsub('<strong><strong>', '<strong>').
gsub('</strong></strong>', '</strong>') # => "<strong>HI</strong>"
Other option would be to use regex to get the desired result.
str.match(/<[a-z]+>[a-zA-Z]+<[\/a-z]+>/)
=> #<MatchData "<strong>HI</strong>">
you can do something like this
str = "<strong><strong>HI</strong></strong>"
p str[/<.*?>/]+ str[/>([^<]*)<\//,1]+str[/<\/.*?>/]
This can be done multiple ways, one of which is using gsub, like this:
str
.gsub(/(<strong>)+/, '<strong>')
.gsub(/(<\/strong>)+/, '</strong>')
The first gsub replaces one or more consecutive instances of <strong> with one <strong>, and the second gsub replaces one or more consecutive instances of </strong> with one </strong> (note the / in the regular expression part needs to be escaped).
It's worth noting that this approach does not ensure there are a matched number of opening and closing <strong> tags.

Freemarker: Output comma separated list as an array

I have a table that has a field that contains a comma separated list of order IDs. What I am trying to do is output each of those IDs separately so that I can use them to look up their corresponding order details in another table.
Does anyone know of a good way to do this?
So far I have tried:
<#data Alerts_test_table as alerts_test>
<#filter
CUSTOMER_ID_=CONTACTS_LIST.CUSTOMER_ID_1>
<#fields AD_ID_LIST>
<#assign seq = ['${alerts_test.AD_ID_LIST}']>
<#list seq?chunk(1) as row><#list row as cell>
${cell}
</#list> </#list>
</#data>
But this just outputs it as a line of text.
Let's say you have comma separated ID-s in idsString, and you want to iterate though the ID-s one by one. Then:
Data-model (with http://try.freemarker.org/ syntax):
idsString = "11, 22, 33"
Template:
<#list idsString?split(r'\s*,\s*', 'r') as idString>
${idString}
</#list>
However, in the template you have posted I see many strange things, so some ideas/pointers:
Be sure that alerts_test.AD_ID_LIST is indeed a String, not a List that you can list directly, without ?split-ing. If it's a String, then '${alerts_test.AD_ID_LIST}' is ultimately the same as alerts_test.AD_ID_LIST. In general, you never need an empty string literal and an ${} in it. It's not useful (but sometimes harmful, as it converts non-string values to string).
?chunk(1) is not useful. The point of ?chunk is to slice a list to smaller lists, but if those smaller lists are to be 1 long, then you might as well just list the items of the original list.
There are no such directives as #data and #filter. Is this some forked FreeMarker version?
If the ID is a number that you need to pass to some API that expects a number, then you will have to convert it to number like idString?number.

Xpath 1.0 using an arithmetic operators

Let's say we have this:
something
Now is there a way to return the #href like: "www.something/page/2". Basically to return the #href value, but with the substring-after(.,"page/") incremented by 1. I've been trying something like
//a/#href[number(substring-after(.,"page/"))+1]
but it doesn't work, and I don't think I can use
//a/#href/number(substring-after(.,"page/"))+1
It's not precisely a paging think, so that I can use the pagination, I just picked that for an example. The point is just to find a way to increment a value in xpath 1.0. Any help?
What you can do is
concat(
translate(//a/#href, '0123456789', ''),
translate(//a/#href, translate(//a/#href, '0123456789', ''), '') + 1
)
So that concatenates the 'href' attribute with all digits being removed with the the sum of 1 and the 'href' with anything but digits being removed.
That might suffice is all digits in your URLs occur at the end of your URL. But generally XPath 1.0 is good at selecting nodes in your input but bad at constructing new values based on parts of node values.
There is a simpler way to achieve this, just take the substring after the page, add 1, and then munge it all back together:
This XPath is based on the current node being the #href attribute:
concat(substring-before(.,'page/'),
'page/',
substring-after(.,'page/')+1
)
Your order of operations is a little, well, out of order. Use something like this:
substring-after(//a/#href, 'page/') + 1
Note that it is not necessary to explicitly convert the string value to a number. From the spec:
The numeric operators convert their operands to numbers as if by
calling the number function.
Putting it all together:
concat(
substring-before(//a/#href, 'page/'),
'page/',
substring-after(//a/#href, 'page/') + 1)
Result:
www.something/page/2

Removing the subscript/Index of an array in awk

I am using the awk's concept of storing the values as a subscript/Index of an array. Please have a look at the code below
stringVariable="hi,bye,cool.hot,how,see";
split(stringVariable,stringArray,",");
#This loop will iterate and stores the RIDs in the requestIds variable into an array
for(tr=1;tr<=length(stringArray);tr++)
{
Count++;
referenceIdArray[stringArray[tr]]++;
}
So in my referenceId array I will be having hi,bye,cool,hot,how,see
let me consider a sample file which has the following values
hi
bye
gone
My aim is to get the values from the file and to match with the array declared previously and if any of the values matches print the value from a file
awk script
awk '{BEGIN (Array loading done previously)} {if($0 in referenceIdArray) {print $0}}'
So this will give me the desired result. But assuming that the "hi" will appear only once in an array and hence when the action block finds the value, the value should be printed and also the corresponding entry in the array which is referenceIdArray["hi"] should also be removed in order to make the search effecient. Since they are stored as subscript I am not sure how to remove the entry. Any suggesions regarding this. Thank you.
You can remove an individual element of an array using the delete statement:
delete array[index]
ref: http://www.math.utah.edu/docs/info/gawk_12.html

Resources