I've created a FreeMarker sequence in my template:
<#assign x = ["red", 16, "blue", "cyan"]>
How do I add additional values to the sequence?
You have to create a new sequence by concatenating x and a sequence containing only the new element:
<#assign x = x + [ "green" ] />
FreeMarker is basically a write-once language. It tries very hard to make it impossible to manipulate data, and that includes modifying arrays or maps, etc.
You can work around this, however, through concatenation and reassignment:
<#assign my_array = [] />
<#list 1..10 as i>
<#assign my_array = my_array + ["value " + i] />
</#list>
This should result in an array containing "value 1" through "value 10". If this seems inelegant it's because it was intended that way. From FreeMarker's ideological perspective, once you've started building arrays, etc., you've moved beyond what the templating language should be doing and into what the models, controllers, helper classes, etc., should be doing in Java code. Working in FreeMarker can become intensely frustrating the more you deviate from this viewpoint.
From http://freemarker.sourceforge.net/docs/app_faq.html#faq_modify_seq_and_map:
The FreeMarkes Template Language doesn't support the modification of sequences/hashes. It's for displaying already calculated things, not for calculating data. Keep templates simple. But don't give it up, you will see some advices and tricks bellow.
Laurent's answer is correct and perfectly acceptable. But you can also add a value using shorthand:
<#assign x += ["green"]>
Now the sequence will look like:
Sequence (5)
0 = "red" (String)
1 = 16 (BigDecimal)
2 = "blue" (String)
3 = "cyan" (String)
4 = "green" (String)
Related
im making a program and i need to combine a lot of variables, most of them strings but i have some int, by doing this
name = "#{variable1}#{variable2}"
name2 = "#{variable2}#{variable1}"
it´s a simple example with just two variables but thats the idea, what im trying to make. i am doing all the possibilities one by one, even when is more than two variables but there are many combinations. Is there an easy way to do it or i have to do it one by one?Also, do i need to write the quotation marks separately or that way is fine?
Is this what you had in mind?
variable1 = "cat"
variable2 = 9
variable3 = "lives"
arr = [variable1, variable2, variable3]
#=> ["cat", 9, "lives"]
arr.join
#=> "cat9lives"
Put all or some of these variables into an array which will produce the combinations easier.
s1 = 'a'
s2 = 'b'
s3 = 'c'
n = 8
[s1, s2, s3, n].combination(3).map(&:join)
=> ["abc", "ab8", "ac8", "bc8"]
Above example assumes that you will pick any of 3 variables from the array and calculate the combinations. You may want to adjust that number to meet your needs.
The whole idea of programming is not doing all possibilities one by one. "there are many combinations": they look like permutations to me. If that is the case:
var1 = "aa"
var2 = "bb"
var3 = 2
res = [var1, var2, var3].permutation.map{|perm| perm.join}
p res #=> ["aabb2", "aa2bb", "bbaa2", "bb2aa", "2aabb", "2bbaa"]
I have a database of "formulas" stored as strings. Let's assume for simplicity, that each formula contains 2 variables denoted by a and b, and that the formulas are all wellformed and it is ensured that it consists only of characters from the set ()ab+-*.
At runtime, formulas are fetched from this database, and from another source, numeric values for a and b are fetched, and the formulas are evaluated. The evaluation can be programmed like this:
# This is how it works right now
formula = fetch_formula(....)
a = fetch_left_arg(....)
b = fetch_right_arg(....)
result = eval(formula)
This design works, but I'm not entirely happy with it. It requires that my program names the free variables exactly the same as they are named in the formula, which is ugly.
If my "formula" would not be a string, but a Proc object or Lambda which accepts two parameters, I could do something like
# No explicitly named variables
result = fetch_proc(...).call(fetch_left_arg(....),fetch_right_arg(....))
but unfortunately, the formulas have to be strings.
I tried to experiment in the following way: What if the method, which fetches the formula from the database, would wrap the string into something, which behaves like a block, and where I could pass parameters to it?
# This does not work of course, but maybe you get the idea:
block_string = "|a,b| #{fetch_formula(....)}"
Of course I can't eval such a block_string, but is there something similar which I could use? I know that instance_eval can pass parameters, but what object should I apply it to? So this is perhaps not an option either....
This is very nasty approach, but for simple formulas you’ve mentioned it should work:
▶ formula = 'a + b'
▶ vars = formula.scan(/[a-z]+/).uniq.join(',') # getting vars names
#⇒ "a,b"
▶ pr = eval("proc { |#{vars}| #{formula} }") # preparing proc
▶ pr.call 3, 5
#⇒ 8
Here we rely on the fact, that parameters are passed to the proc in the same order, as they appear in the formula.
If I get your question correctly, it is something that I have done recently, and is fairly easy. Given a string:
s = "{|x, y| x + y}"
You can create a proc by doing:
eval("Proc.new#{s}")
One way to avoid creating the variables in the local scope could be to use a Binding:
bind = binding
formula = fetch_formula(....)
bind.local_variable_set :a, fetch_left_arg(....)
bind.local_variable_set :b, fetch_right_arg(....)
result = bind.eval(formula)
The variables a and b now only exist in the binding, and do not pollute the rest of your code.
You can create a lambda from string, as shown below:
formula = "a + b"
lambda_template = "->(a,b) { %s }"
formula_lambda = eval(lambda_template % formula)
p formula_lambda.call(1,2)
#=> 3
Say I have some deeply nested array structure and a reference to an object inside:
strings = ["1", "2", " 3"]
nested = [[strings] * 10] * 10
reference = nested[0][0][0]
How do I replace the object reference points to with eg. "4"? I need somthing generic that works with arbitrary objects, not String#gsub! and friends. Something like Object#replace(other_obj).
You can't, we don't have (explicit) pointers in Ruby, we have (implicit) references but you can't dereference them to mess with what they contain. Instead, you need to do something like:
inner nested[0][0]
inner[0] = '4'
so that you can work with a reference to the element you want to replace rather than the element itself.
Of course, with the structure in your question, that inner[0] = '4' will replace the first element of strings (and thus every element of nested since it is just a pile of references to the same array that strings references.
Sorry about how overloaded the term reference is here. It is a horrible abuse of English but English itself is an abuse of English :)
Consider the following Ruby code:
a = ["x"] * 3 # or a = Array.new(3, "x")
a[0].insert(0, "a")
a.each {|i| puts i}
I would expect the output to be ax, x, x (on new lines of course). However, with Ruby 1.9.1 the output is ax, ax, ax. What's going on? I've narrowed the problem down to the way the array a is defined. If I explicitly write out
a = ["x", "x", "x"]
then the code works as expected, but either version in the original code gives me this unexpected behaviour. It appears that the */initializer means the copies are actually references to the same copy of the string "x". However, if instead of the insert command I write
a[0] = "a" + a[0]
Then I get the desired output. Is this a bug, or is there some feature at work which I'm not understanding?
The documentation to Array.new(size=0, obj=nil):
... it is created with size copies of obj (that is, size references to the same obj).
and Array * int:
... returns a new array built by concatenating the int copies of self
So in both of the forms you're surprised by, you end up with three references to the same "x" object, just as you figured out. I'd say you might argue about the design decision, but it's a documented intentional behavior, not a bug.
The best way I know to get the behavior you want without manually writing the array literal (["x", "x", "x"]) is
a = Array.new(3) {"x"}
Or course, with just three elements, it doesn't much matter, but with anything much bigger, this form comes in handy.
In short, although "x" is just a literal, it is an object. You use ["x'] * 3 so a is containing 3 same object. You insert 'a' to one of them, they will be all changed.
I have a key => value table I'd like to sort in Lua. The keys are all integers, but aren't consecutive (and have meaning). Lua's only sort function appears to be table.sort, which treats tables as simple arrays, discarding the original keys and their association with particular items. Instead, I'd essentially like to be able to use PHP's asort() function.
What I have:
items = {
[1004] = "foo",
[1234] = "bar",
[3188] = "baz",
[7007] = "quux",
}
What I want after the sort operation:
items = {
[1234] = "bar",
[3188] = "baz",
[1004] = "foo",
[7007] = "quux",
}
Any ideas?
Edit: Based on answers, I'm going to assume that it's simply an odd quirk of the particular embedded Lua interpreter I'm working with, but in all of my tests, pairs() always returns table items in the order in which they were added to the table. (i.e. the two above declarations would iterate differently).
Unfortunately, because that isn't normal behavior, it looks like I can't get what I need; Lua doesn't have the necessary tools built-in (of course) and the embedded environment is too limited for me to work around it.
Still, thanks for your help, all!
You seem to misunderstand something. What you have here is a associative array. Associative arrays have no explicit order on them, e.g. it's only the internal representation (usually sorted) that orders them.
In short -- in Lua, both of the arrays you posted are the same.
What you would want instead, is such a representation:
items = {
{1004, "foo"},
{1234, "bar"},
{3188, "baz"},
{7007, "quux"},
}
While you can't get them by index now (they are indexed 1, 2, 3, 4, but you can create another index array), you can sort them using table.sort.
A sorting function would be then:
function compare(a,b)
return a[1] < b[1]
end
table.sort(items, compare)
As Komel said, you're dealing with associative arrays, which have no guaranteed ordering.
If you want key ordering based on its associated value while also preserving associative array functionality, you can do something like this:
function getKeysSortedByValue(tbl, sortFunction)
local keys = {}
for key in pairs(tbl) do
table.insert(keys, key)
end
table.sort(keys, function(a, b)
return sortFunction(tbl[a], tbl[b])
end)
return keys
end
items = {
[1004] = "foo",
[1234] = "bar",
[3188] = "baz",
[7007] = "quux",
}
local sortedKeys = getKeysSortedByValue(items, function(a, b) return a < b end)
sortedKeys is {1234,3188,1004,7007}, and you can access your data like so:
for _, key in ipairs(sortedKeys) do
print(key, items[key])
end
result:
1234 bar
3188 baz
1004 foo
7007 quux
hmm, missed the part about not being able to control the iteration. there
But in lua there is usually always a way.
http://lua-users.org/wiki/OrderedAssociativeTable
Thats a start. Now you would need to replace the pairs() that the library uses. That could be a simples as pairs=my_pairs. You could then use the solution in the link above
PHP arrays are different from Lua tables.
A PHP array may have an ordered list of key-value pairs.
A Lua table always contains an unordered set of key-value pairs.
A Lua table acts as an array when a programmer chooses to use integers 1, 2, 3, ... as keys. The language syntax and standard library functions, like table.sort offer special support for tables with consecutive-integer keys.
So, if you want to emulate a PHP array, you'll have to represent it using list of key-value pairs, which is really a table of tables, but it's more helpful to think of it as a list of key-value pairs. Pass a custom "less-than" function to table.sort and you'll be all set.
N.B. Lua allows you to mix consecutive-integer keys with any other kinds of keys in the same table—and the representation is efficient. I use this feature sometimes, usually to tag an array with a few pieces of metadata.
Coming to this a few months later, with the same query. The recommended answer seemed to pinpoint the gap between what was required and how this looks in LUA, but it didn't get me what I was after exactly :- which was a Hash sorted by Key.
The first three functions on this page DID however : http://lua-users.org/wiki/SortedIteration
I did a brief bit of Lua coding a couple of years ago but I'm no longer fluent in it.
When faced with a similar problem, I copied my array to another array with keys and values reversed, then used sort on the new array.
I wasn't aware of a possibility to sort the array using the method Kornel Kisielewicz recommends.
The proposed compare function works but only if the values in the first column are unique.
Here is a bit enhanced compare function to ensure, if the values of a actual column equals, it takes values from next column to evaluate...
With {1234, "baam"} < {1234, "bar"} to be true the items the array containing "baam" will be inserted before the array containing the "bar".
local items = {
{1004, "foo"},
{1234, "bar"},
{1234, "baam"},
{3188, "baz"},
{7007, "quux"},
}
local function compare(a, b)
for inx = 1, #a do
-- print("A " .. inx .. " " .. a[inx])
-- print("B " .. inx .. " " .. b[inx])
if a[inx] == b[inx] and a[inx + 1] < b[inx + 1] then
return true
elseif a[inx] ~= b[inx] and a[inx] < b[inx] == true then
return true
else
return false
end
end
return false
end
table.sort(items,compare)