Why doesn't this variable display on page in Sinatra - ruby

Trying to show the #total variable but it always says 0.
What's the correct way to get it to display on the page?
Currently i am doing...
main.rb
require 'sinatra'
get '/' do
#array = [1, 7, 3, 0]
#index = params[:index].to_i
#total = 1
def get_products_of_all_ints_except_at_index()
#array.delete_at(#index)
#array.each do |i|
#total *= i
end
end
get_products_of_all_ints_except_at_index()
erb :home
end
home.erb
<form action="/">
<input type="number" name="index" placeholder="index">
<button>Calculate</button>
</form>
<%= #total %>

In your #array, the last element is 0. Because you are iterating over it and multiplying the total with each element, total is 0 too.

Related

Ruby Fibonacci Multiplication Table [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Ruby Fibonacci Multiplication Table This was an interview question.
Recently jumped into software development, and came across this challenge. Can you show me below, how can I write the Fibonacci multiplication table in Ruby language? For the last couple of days, I was trying to implement it but seems like I am facing a brick wall and the code makes me feel insane and also I failed on the interview, but that does not matter at the moment. I will appreciate any kind of help. Thanks a lot.
ApplicationController:
class ApplicationController < Sinatra::Base
configure do
set :public_folder, 'public'
set :views, 'app/views'
end
get '/' do
#time_of_day = Time.now
erb :index
end
end
FibonacciController:
class FibonacciController < ApplicationController
get '/fibonacci' do
place = params[:place].to_i
#sequence = fib(place)
erb :fibonacci
end
def fib(place)
res = []
a = 0
b = 1
while b < place do
res << b
a,b = b,a+b
end
res
end
end
Fibonacci.erb
<div class="container">
<h1> Fibonacci sequence: </h1>
<div class="sub-container">
<p> Generated fibonacci sequence: </p>
<%= #sequence.join(', ') %>
</div>
</div>
Index.erb
<div class="container">
Date and time: <%= #time_of_day %>
<br>
<h1> Fibonacci Multiplication Table </h1>
<p> Enter your number below: </p>
<form method="GET" action="/fibonacci">
<label for="sequence">
<input type="integer" name="place" placeholder="Insert your number">
<input type="submit">
</form>
</div>
(This is the ultimate goal of this challenge)
FibonacciController code
class FibonacciController < ApplicationController
get '/fibonacci' do
place = params[:place].to_i
sequence = fib(place)
#table = generate_table(sequence)
erb :fibonacci
end
def fib(place)
return [] if place <= 0
a = 0
b = 1
res = [a]
while res.length < place do
res << b
a,b = b, a+b
end
res
end
def generate_table(sequence)
return [] if sequence.length.zero?
cols = []
(sequence.length + 1).times do |row|
row_data = []
(sequence.length + 1).times do |col|
row_data << generate_table_element(row, col, sequence)
end
cols << row_data
end
cols
end
def generate_table_element(row, col, sequence)
return '_' if row.zero? && col.zero?
return sequence[col - 1] if row.zero?
return sequence[row - 1] if col.zero?
sequence[col - 1] * sequence[row - 1]
end
end
And in erb file
<p> Generated fibonacci sequence: </p>
<% #table.each do |table_row| %>
<%= table_row.join(',') %>
<br/>
<% end %>

Print the first letter in the view but I don't need to repeat the letter

I'm making a list of categories but I need the header to only show the first letter without repeating
This is for a list of all the categories of a store
Controller:
def show
#category = Category.friendly.find(params[:id])
#category_articles = #category.articles.paginate(page: params[:page], per_page: 12)
end
view:
<div class="container" id="tag-container">
<% #categories.each do |category| %>
<section>
<h2><%= category.name.first %></h2>
<%= link_to "#{category.name}", category_path(category)%>
<span>(<%= pluralize(category.articles.count,"")%>)</span>
</section>
<% end %>
</div>
I'll really appreciate if you can help me with this.
Supposing categories to be sorted by name, this can be an option. I'm using plain Ruby, but you can do the same with Rails. Consider categories array as the collection of records.
categories = %W(bat bet bot cat cut dot git got gut)
grouped_categories = categories.group_by { |w| w[0] }
Grouping by first letter ({ |w| w[0] }) using Enumerable#group_by. The method returns a Hash that you can iterate with nested loop:
grouped_categories
#=> {"b"=>["bat", "bet", "bot"], "c"=>["cat", "cut"], "d"=>["dot"], "g"=>["git", "got", "gut"]}
grouped_categories.each do |initial, vals|
puts "-#{initial}"
vals.each do |val|
puts "----#{val}"
end
end
It prints:
-b
----bat
----bet
----bot
-c
----cat
----cut
-d
----dot
-g
----git
----got
----gut
If you wish the categories alphabetised,
categories = ["gut", "git", "bot", "cut", "got", "cat", "dot", "bet", "bat"]
categories.sort.chunk { |w| w[0] }.each { |ltr,a| puts "#{ltr}: #{a.join(' ')}" }
b: bat bet bot
c: cat cut
d: dot
g: git got gut

each_with_index_do starting at 1 for index

I am using a ruby iterator on a view in a rails app like so:
<% (1..#document.data.length).each_with_index do |element, index| %>
...
<% end %>
I thought the addition of the 1.. instead of just saying:
#document.data
would get the trick of having the index above start at 1. But alas, the above code index is still 0 to data.length (-1 effectively). So what am I doing wrong, i need the index to equal 1-data.length...no clue how to set up the iterator to do this.
Unless you're using an older Ruby like 1.8 (I think this was added in 1.9 but I'm not sure), you can use each.with_index(1) to get a 1-based enumerator:
In your case it would be like this:
<% #document.data.length.each.with_index(1) do |element, index| %>
...
<% end %>
I think maybe you misunderstand each_with_index.
each will iterate over elements in an array
[:a, :b, :c].each do |object|
puts object
end
which outputs;
:a
:b
:c
each_with_index iterates over the elements, and also passes in the index (starting from zero)
[:a, :b, :c].each_with_index do |object, index|
puts "#{object} at index #{index}"
end
which outputs
:a at index 0
:b at index 1
:c at index 2
if you want it 1-indexed then just add 1.
[:a, :b, :c].each_with_index do |object, index|
indexplusone = index + 1
puts "#{object} at index #{indexplusone}"
end
which outputs
:a at index 1
:b at index 2
:c at index 3
if you want to iterate over a subset of an array, then just choose the subset, then iterate over it
without_first_element = array[1..-1]
without_first_element.each do |object|
...
end
This may not be exactly the same each_with_index method in question, but I think the result may close to something in mod is asking...
%w(a b c).each.with_index(1) { |item, index| puts "#{index} - #{item}" }
# 1 - a
# 2 - b
# 3 - c
For more information https://ruby-doc.org/core-2.6.1/Enumerator.html#method-i-with_index
Use Integer#next:
[:a, :b, :c].each_with_index do |value, index|
puts "value: #{value} has index: #{index.next}"
end
produces:
value: a has index: 1
value: b has index: 2
value: c has index: 3
There is no such thing as making the index start from 1. If you want to skip the first item in the array use next.
<% (1..#document.data.length).each_with_index do |element, index| %>
next if index == 0
<% end %>
An array index is always going to be zero based.
If you want to skip the first element, which it sounds like you do:
#document.data[1..-1].each do |data|
...
end
If I understand your question right, you want to start the index from 1, but in ruby arrays goes as 0 base indexes, so the simplest way would be
given #document.data is an array
index = 1
#document.data.each do |element|
#your code
index += 1
end
HTH
I had the same problem, and solved it by using the each_with_index method. But added 1 to the index in the code.
#someobject.each_with_index do |e, index|
= index+1

How to parse consecutive tags with Nokogiri?

I have HTML code like this:
<div id="first">
<dt>Label1</dt>
<dd>Value1</dd>
<dt>Label2</dt>
<dd>Value2</dd>
...
</div>
My code does not work.
doc.css("first").each do |item|
label = item.css("dt")
value = item.css("dd")
end
Show all the <dt> tags firsts and then the <dd> tags and I need "label: value"
First of all, your HTML should have the <dt> and <dd> elements inside a <dl>:
<div id="first">
<dl>
<dt>Label1</dt>
<dd>Value1</dd>
<dt>Label2</dt>
<dd>Value2</dd>
...
</dl>
</div>
but that won't change how you parse it. You want to find the <dt>s and iterate over them, then at each <dt> you can use next_element to get the <dd>; something like this:
doc = Nokogiri::HTML('<div id="first"><dl>...')
doc.css('#first').search('dt').each do |node|
puts "#{node.text}: #{node.next_element.text}"
end
That should work as long as the structure matches your example.
Under the assumption that some <dt> may have multiple <dd>, you want to find all <dt> and then (for each) find the following <dd> before the next <dt>. This is pretty easy to do in pure Ruby, but more fun to do in just XPath. ;)
Given this setup:
require 'nokogiri'
html = '<dl id="first">
<dt>Label1</dt><dd>Value1</dd>
<dt>Label2</dt><dd>Value2</dd>
<dt>Label3</dt><dd>Value3a</dd><dd>Value3b</dd>
<dt>Label4</dt><dd>Value4</dd>
</dl>'
doc = Nokogiri.HTML(html)
Using no XPath:
doc.css('dt').each do |dt|
dds = []
n = dt.next_element
begin
dds << n
n = n.next_element
end while n && n.name=='dd'
p [dt.text,dds.map(&:text)]
end
#=> ["Label1", ["Value1"]]
#=> ["Label2", ["Value2"]]
#=> ["Label3", ["Value3a", "Value3b"]]
#=> ["Label4", ["Value4"]]
Using a Little XPath:
doc.css('dt').each do |dt|
dds = dt.xpath('following-sibling::*').chunk{ |n| n.name }.first.last
p [dt.text,dds.map(&:text)]
end
#=> ["Label1", ["Value1"]]
#=> ["Label2", ["Value2"]]
#=> ["Label3", ["Value3a", "Value3b"]]
#=> ["Label4", ["Value4"]]
Using Lotsa XPath:
doc.css('dt').each do |dt|
ct = dt.xpath('count(following-sibling::dt)')
dds = dt.xpath("following-sibling::dd[count(following-sibling::dt)=#{ct}]")
p [dt.text,dds.map(&:text)]
end
#=> ["Label1", ["Value1"]]
#=> ["Label2", ["Value2"]]
#=> ["Label3", ["Value3a", "Value3b"]]
#=> ["Label4", ["Value4"]]
After looking at the other answer here is an inefficient way of doing the same thing.
require 'nokogiri'
a = Nokogiri::HTML('<div id="first"><dt>Label1</dt><dd>Value1</dd><dt>Label2</dt><dd>Value2</dd></div>')
dt = []
dd = []
a.css("#first").each do |item|
item.css("dt").each {|t| dt << t.text}
item.css("dd").each {|t| dd << t.text}
end
dt.each_index do |i|
puts dt[i] + ': ' + dd[i]
end
In css to reference the ID you need to put the # symbol before. For a class it's the . symbol.

xpath to find all following sibling adjacent nodes up til another type [duplicate]

I have HTML code like this:
<div id="first">
<dt>Label1</dt>
<dd>Value1</dd>
<dt>Label2</dt>
<dd>Value2</dd>
...
</div>
My code does not work.
doc.css("first").each do |item|
label = item.css("dt")
value = item.css("dd")
end
Show all the <dt> tags firsts and then the <dd> tags and I need "label: value"
First of all, your HTML should have the <dt> and <dd> elements inside a <dl>:
<div id="first">
<dl>
<dt>Label1</dt>
<dd>Value1</dd>
<dt>Label2</dt>
<dd>Value2</dd>
...
</dl>
</div>
but that won't change how you parse it. You want to find the <dt>s and iterate over them, then at each <dt> you can use next_element to get the <dd>; something like this:
doc = Nokogiri::HTML('<div id="first"><dl>...')
doc.css('#first').search('dt').each do |node|
puts "#{node.text}: #{node.next_element.text}"
end
That should work as long as the structure matches your example.
Under the assumption that some <dt> may have multiple <dd>, you want to find all <dt> and then (for each) find the following <dd> before the next <dt>. This is pretty easy to do in pure Ruby, but more fun to do in just XPath. ;)
Given this setup:
require 'nokogiri'
html = '<dl id="first">
<dt>Label1</dt><dd>Value1</dd>
<dt>Label2</dt><dd>Value2</dd>
<dt>Label3</dt><dd>Value3a</dd><dd>Value3b</dd>
<dt>Label4</dt><dd>Value4</dd>
</dl>'
doc = Nokogiri.HTML(html)
Using no XPath:
doc.css('dt').each do |dt|
dds = []
n = dt.next_element
begin
dds << n
n = n.next_element
end while n && n.name=='dd'
p [dt.text,dds.map(&:text)]
end
#=> ["Label1", ["Value1"]]
#=> ["Label2", ["Value2"]]
#=> ["Label3", ["Value3a", "Value3b"]]
#=> ["Label4", ["Value4"]]
Using a Little XPath:
doc.css('dt').each do |dt|
dds = dt.xpath('following-sibling::*').chunk{ |n| n.name }.first.last
p [dt.text,dds.map(&:text)]
end
#=> ["Label1", ["Value1"]]
#=> ["Label2", ["Value2"]]
#=> ["Label3", ["Value3a", "Value3b"]]
#=> ["Label4", ["Value4"]]
Using Lotsa XPath:
doc.css('dt').each do |dt|
ct = dt.xpath('count(following-sibling::dt)')
dds = dt.xpath("following-sibling::dd[count(following-sibling::dt)=#{ct}]")
p [dt.text,dds.map(&:text)]
end
#=> ["Label1", ["Value1"]]
#=> ["Label2", ["Value2"]]
#=> ["Label3", ["Value3a", "Value3b"]]
#=> ["Label4", ["Value4"]]
After looking at the other answer here is an inefficient way of doing the same thing.
require 'nokogiri'
a = Nokogiri::HTML('<div id="first"><dt>Label1</dt><dd>Value1</dd><dt>Label2</dt><dd>Value2</dd></div>')
dt = []
dd = []
a.css("#first").each do |item|
item.css("dt").each {|t| dt << t.text}
item.css("dd").each {|t| dd << t.text}
end
dt.each_index do |i|
puts dt[i] + ': ' + dd[i]
end
In css to reference the ID you need to put the # symbol before. For a class it's the . symbol.

Resources