I'm looking for a Freemarker template that can output a List to console in tabular format.
<#list ["foo", "bar", "baz", "huhu", "lala", "keke", "koko", "fifi", "bubu"] as x>
${x}
</#list>
I'm looking for console output like:
foo bar baz
huhu lala keke
koko fifi bubu
I think ${x?item_cycle('col1', 'col2', 'col3')} maybe the way to go, adding a line break only for col3 items. But how can I do if else logic on item_cycle?
The nicest way of adding line breaks is probably with ?chunk(n). Also, the column width (which you haven't asked about) can for example be ensured with ?right_pad(n). So the example is:
<#list ["foo", "bar", "baz", "huhu", "lala", "keke", "koko", "fifi", "bubu"]?chunk(3) as row>
<#list row as x>${x?right_pad(10)}</#list>
</#list>
BTW, as you have asked, of course you can write things like <#if x?item_cycle(...) == ...>, or even ${x}${x?item_cycle('', '', '\n')}, or <#if x?item_count % 3 == 0>, but these are uglier solutions.
Related
I've got an array of strings. A few of the strings in this array contain a certain substring I'm looking for. I want to get an array of those strings containing the substring.
I would hope to do it like this:
a = ["abc", "def", "ghi"]
o.select(&:include?("c"))
But that gives me this error:
(repl):2: syntax error, unexpected ')', expecting end-of-input
o.select(&:include?("c"))
^
If your array was a file lines.txt
abc
def
ghi
Then you would select the lines containing c with the grep command-line utility:
$ grep c lines.txt
abc
Ruby has adopted this as Enumerable#grep. You can pass a regular expression as the pattern and it returns the strings matching this pattern:
['abc', 'def', 'ghi'].grep(/c/)
#=> ["abc"]
More specifically, the result array contains all elements for which pattern === element is true:
/c/ === 'abc' #=> true
/c/ === 'def' #=> false
/c/ === 'ghi' #=> false
You can use the &-shorthand here. It's rather irrational (don't do this), but possible.
If you do manage to find an object and a method so you can make checks in your select like so:
o.select { |e| some_object.some_method(e) }
(the important part is that some_object and some_method need to be the same in all iterations)
...then you can use Object#method to get a block like that. It returns something that implements to_proc (a requirement for &-shorthand) and that proc, when called, calls some_method on some_object, forwarding its arguments to it. Kinda like:
o.m(a, b, c) # <=> o.method(:m).to_proc.call(a, b, c)
Here's how you use this with the &-shorthand:
collection.select(&some_object.method(:some_method))
In this particular case, /c/ and its method =~ do the job:
["abc", "def", "ghi"].select(&/c/.method(:=~))
Kinda verbose, readability is relatively bad.
Once again, don't do this here. But the trick can be helpful in other situations, particularly where the proc is passed in from the outside.
Note: you may have heard of this shorthand syntax in a pre-release of Ruby 2.7, which was, unfortunately, reverted and didn't make it to 2.7:
["abc", "def", "ghi"].select(&/c/.:=~)
You are almost there, you cannot pass parameter in &:. You can do something like:
o.select{ |e| e.include? 'c' }
I just wanted to use a heredoc as a value in a hash literal. While it works fine if the heredoc is the very last element:
{
foo: 123,
bar: <<-HEREDOC
a longer text
HEREDOC
}
#=> {:foo=>123, :bar=>" a longer text\n"}
I couldn't find a way to add another key-value pair after the heredoc. Or, more specifically, I couldn't find a way to insert the separating comma without causing a syntax error:
{
foo: 123,
bar: <<-HEREDOC
a longer text
HEREDOC
# <- causes a syntax error because a comma is missing here, but where to put it?
baz: 456
}
This seems to work
{
foo: 123,
bar: <<-HEREDOC,
a longer text
HEREDOC
baz: 456
}
Ursus' answer is spot on. The reason why this works is that the heredoc doesn't start immediately after the opening identifier, but on the line following the opening identifier. Everything after the opening identifier (on the same line) is parsed as usual.
This not only allows you to put the , right after the <<-HEREDOC, it allows you to define the entire hash in one line:
{ foo: 123, bar: <<-HEREDOC, baz: 456 }
a longer text
HEREDOC
#=> {:foo=>123, :bar=>" a longer text\n", :baz=>456}
You could also pass two heredocs: (using ~ instead of - strips whitespace)
{ foo: 123, bar: <<~BAR, baz: <<~BAZ }
bar's value
BAR
baz's value
BAZ
#=> {:foo=>123, :bar=>"bar's value\n", :baz=>"baz's value\n"}
Ruby's heredoc documentation contains similar examples, but unfortunately RDoc doesn't get it right, so they are often overlooked:
To call a method on a heredoc place it after the opening identifier:
expected_result = <<-EXPECTED.chomp
One plus one is #{1 + 1}
EXPECTED
You may open multiple heredocs on the same line, but this can be
difficult to read:
puts(<<-ONE, <<-TWO)
content for heredoc one
ONE
content for
heredoc two
TWO
Assuming I have:
[24] pry(main)> str="these (are) things (that) I want (to) know"
and I want
=> ["these", "things", "I want", "know"]
but
[25] pry(main)> str.split(/\(.*\)/)
I get:
=> ["these ", " know"]
[26] pry(main)>
How would I fix this? Sorry for multiple questions - a bit seperate issues.
edit #1
since we're splitting on a Regex, is there any way to also get the matched elements back?
like:
=> [["these", "things", "I want", "know"],["(are)","(that)","(too)"]]
where the first part is the splitted values and the second is the matched array?
Make the * quantifier ungreedy by putting a ? after it. Like so:
str.split(/\(.*?\)/)
.* without ? will match as much as possible, while you want the opposite effect.
You could also use a different approach and restrict what characters you want to match. For example:
str.split(/\([^()]*\)/)
Non regexp version:
s = "these (are) things (that) I want (to) know"
is_parenthesised = -> x {x.start_with?('(') && x.end_with?(')')}
p s.split(' ').partition &is_parenthesised #=> [["(are)", "(that)", "(to)"], ["these", "things", "I", "want", "know"]]
Here's another way:
[str.gsub(/\s*\(.*?\)\s*/, 0.chr).split(0.chr), str.scan(/(\(.*?\))/).flatten]
#=> [["these", "things", "I want", "know"], ["(are)", "(that)", "(to)"]]
I could have gsub'ed to any string I was certain was not in the data. ASCII 0 seemed a safe choice. split is definitely better for the first element, but I offer this in the interest of diversity.
I have the array:
example = ['foo', 'bar', 'quux']
I want to iterate over it and print it so it comes out like: foo bar quux, not ['foo', 'bar', 'quux'] which would be the case if I used each or for.
Note: I can't just do: example[0];example[1], etc. because the length of the array is variable.
How do I do this?
Here:
puts array.join(' ') # The string contains one space
example.join(" ") #=> foo bar quux.
If you used each to print, it would work fine:
example.each {|item| print item; print " " } #=> foo bar quux
However, if what you want is a string with the items separated by spaces, that's what the join method is for:
example.join(' ') #=> "foo bar quux"
I suspect your problem is that you're confusing printing with iterating, as each just returns the original array — if you want things printed inside of it, you need to actually print like I did in the example above.
if they may be printed underneath each other just use
puts example
=>
foo
bar
quux
otherwise use the solutions from the other answers
puts example.join(" ")
i am a ruby beginner and i found a problem, i would like to know if there is a more 'ruby way'
to solve it.
my problem is:
i got a string, like this:
str = "<div class=\"yui-u first\">\r\n\t\t\t\t\t<h1>Jonathan Doe</h1>\r\n
\t\t\t\t\t<h2>Web Designer, Director</h2>\r\n\t\t\t\t</div>"
# now, i want to replace the substring in <h1> </h1> and <h2> and </h2> with
these two string:"fooo" and "barr".
here is what i did:
# first, i got the exactly matched substrings of str:
r = str.scan(/(?<=<h\d>).*?(?=<\/h\d>)/)
# then, i create a hash table to set the corresponding replace strings
h = {r[0] => 'fooo', r[1] => 'barr'}
# finally, using str.gsub to replace those matched strings
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/, h)
# or like this
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/) {|v| h[v]}
PS: The substring in <h1> </h1> and <h2> </h2> are not fixed, so i have
to get these strings FIRST, so that i can build a hash table. But I
really don't like the code above (because i wrote two lines almost the same),
i think there must be a elegant way to do so. i have tried something like this:
str.gsub!(/(?<=<h\d>).*?(?=<\/h\d>)/) { ['fooo', 'barr'].each {|v| v}}
but this didn't work. because this block returns ['fooo', 'barr'] EVERYTIME!
if there is a way to let this block (or something?) return one element at a time(return 'fooo' at the first time, then return 'barr' at the second), my problem will be solved!
thank you!
Although you really have no business parsing HTML with a regexp, as a library like Nokogiri can make this significantly easier as you can modify the DOM directly, the mistake you're making is in presuming that the iterator will execute only once per substitution and that the block will return only one value. each will actually return the object being iterated.
Here's a way to avoid all the Regexp insanity:
require 'rubygems'
gem 'nokogiri'
require 'nokogiri'
str = "<div class=\"yui-u first\">\r\n\t\t\t\t\t<h1>Jonathan Doe</h1>\r\n
\t\t\t\t\t<h2>Web Designer, Director</h2>\r\n\t\t\t\t</div>"
html = Nokogiri::HTML(str)
h1 = html.at_css('h1')
h1.content = 'foo'
h2 = html.at_css('h2')
h2.content = 'bar'
puts html.to_s
If you want to do multiple substitutions where each gets a different value, the simple way is to just rip off values from a stack:
subs = %w[ foo bar baz ]
string = "x x x"
string.gsub!(/x/) do |s|
subs.shift
end
puts string.inspect
# => "foo bar baz"
Keep in mind that subs is consumed here. A more efficient approach would be to increment some kind of index variable and use that value instead, but this is a trivial modification.