next and previous for letters and symbols array [duplicate] - ruby

This question already has an answer here:
What is the opposite of string.next?
(1 answer)
Closed 9 years ago.
Because
"A".next => "B"
and
"#".next => "$"
How would I find the previous item? So that:
"$".previous => "#"

If you only need it to work on single character strings, you could extend String:
class String
def previous
return (self.ord - 1).chr
end
end
Then:
"$".previous # => "#"
I'm not a big ruby programmer, so I don't know how bad of a practice this is, but it does work if you need it.

Here's one way to do it for individual characters:
('B'.ord-1).chr # => 'A'
('$'.ord-1).chr # => '#'

From What is the opposite of string.next?
prev or something similar is not in the standard API because succ and a hypoethetical prev are surjective. Despite this, "Implement Ruby String Class Prev / Pred / Prev! / Pred! - Opposite Of Next / Succ Methods" is a possible version you could use.
The root problem is that succ is not inversible. This means, once you applied succ, then prev would end up with some ambiguity.
Credits to Bjoern Rennhak.

Related

What does "!" symbol mean in Ruby language [duplicate]

This question already has answers here:
Exclamation points before a variable in Ruby
(3 answers)
Closed 2 years ago.
For example: what is this saying:
if !result[movie[:studio]]
result[movie[:studio]] = movie[:worldwide_gross]
else
result[movie[:studio]] += movie[:worldwide_gross]
end
i += 1
end
This is a solution to manipulating an NDS, or rather getting some information from an NDS and I can't seem to find what the !result means.
The ! negates the element. So if result[movie[:studio]] is truthy then !result[movie[:studio]] is the opposite, falsy. Your conditional statement is basically saying that if there is no value for the studio key then give it a value of movie[:worldwide_gross], otherwise add to the current value.
If you do not like the ! you could consider using unless instead or swap the order of the conditional.
if result[movie[:studio]]
result[movie[:studio]] += movie[:worldwide_gross]
else
result[movie[:studio]] = movie[:worldwide_gross]
end
! negates the element as it was already mentioned.
So, !true => false
So if you do
if !hungry
do x
end
You will execute X if you are not hungry.
It might also be used on null. So you can use it to check if "not null". This might be the use case that you're seeing.

Ruby blocks behave unexpectedly when using "do" [duplicate]

This question already has answers here:
do..end vs curly braces for blocks in Ruby
(14 answers)
Closed 5 years ago.
I was trying to solve a coding puzzle: Take strings, and count the ones that don't include repeated words.
This code works:
def validate(passphrase)
words = passphrase.split
words == words.uniq
end
passphrases = File.readlines("../input/passphrases.txt")
p passphrases.count {|phrase| validate(phrase)}
#=> 337
If I make one minor change with the count block, it counts all of the passphrases instead of just the ones that would return true when passed through the block:
p passphrases.count do |phrase|
validate(phrase)
end
#=>512
What's up with this?
It is due to argument precedence with the do block.
Your first example is equivalent to:
p(passphrases.count {|phrase| validate(phrase)})
The second one with the do block is equivalent to:
p(passphrases.count) do |phrase|
validate(phrase)
end
Where the do is being applied to the p function.
If you want the second case to match the first, wrap the whole block in parenthesis:
p(passphrases.count do |phrase|
validate(phrase)
end)

what is the difference between .capitalize and .capitalize!(or .map & .map!...etc.) and in ruby [duplicate]

This question already has answers here:
What is the purpose of "!" and "?" at the end of method names?
(5 answers)
Closed 6 years ago.
learning how to code with Ruby and was trying learn from test first.
and I stumbled something funny.
I was trying to capitalize every word but
title = 'stuart little'
a = title.split
a.each do |x|
x.capitalize
end
a.join(' ')
This one's result is 'stuart little'
but if I add the ! in capitalize
title = 'stuart little'
a = title.split
a.each do |x|
x.capitalize!
end
a.join(' ')
it ends up with the result I want which is 'Stuart Little'
just .capitalize should work shouldn't it? since I'm just capitalizing the words. and what makes .capitalize! work in this scenario?
When a method has a ! at the end in Ruby, it is commonly referred to as a bang-method. The exclamation point indicates that the method is the dangerous version of another method.
In this case, capitalize! will modify your string, while capitalize will return a new string object. Since you are later calling on your original objects (the strings in a), your code will only work with capitalize!. To make the code work with capitalize, you would have to set that index of the array to the result of the method, e.g. a[index] = x.capitalize
if you really want to learn I like to go to the source
for map for map!. the source would tell you what the difference is
map- Invokes the given block once for each element of self.
and
map! - Invokes the given block once for each element of self,
replacing the element with the value returned by the block.

How do i print a string with repeated names followed by a number - Ruby? [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 6 years ago.
Improve this question
How do i print a name Ex. John1 and then print after John2, john3, john4, john5 and so one in an infinite number
I started using ruby today and I'm having some trouble figuring this out. I've searched some but can't find anything so how would I do this?
It's to mass produce accounts to the staff of a certain company and I found ruby to be the smartest to write it in and I will never use it again after this
Keep it simple.
puts (1..5).map { |n| "john#{n}" }
john1
john2
john3
john4
john5
The class Range includes the module Enumerable (as does the classes Array, Hash and others). By doing so, instances of Range (such as 1..5) gain the use of all of Enumerable's instance methods. One of Enumerable's instance methods is used here: Enumerable#map.
For printing a simple series like this:
n = 1
loop do
print 'john%d, ' % n
n += 1
end
That will never terminate, which makes it kind of silly. Maybe what you want is a bounded range:
list = (1..10).map do |n|
'john%d' % n
end.join(', ')
puts list
You can adjust the start and end values as necessary.
Perhaps use an enumerator here:
enum = Enumerator.new do |y|
i = 1
loop do
y << "John#{i}"
i += 1
end
end
enum.next #=> "John1"
enum.next #=> "John2"
enum.next #=> "John3"
Then use any one of the methods available to instances of Enumerator. Here we've used Enumerator#next to get the next "John" string.
One simple way is using a for loop. First declare an empty string variable that will hold our contents.
One important thing to consider is the index of the loop. If it's the last item, we do not want to add a separator like ", "
This is where the conditional comes into play. If the index is less than the last, we will add a comma and space, otherwise just the name.
Interpolation is done by wrapping a variable inside #{ and }
str = ""
for i in 1..5
str += i < 5 ? "john#{i}, " : "john#{i}"
end
Returns
"john1, john2, john3, john4, john5"

ruby check whether string in csv will be mistaken for a date (in excel)

I have a function in my Rails app that creates a csv. When the user opens that csv in Excel many times there are fields that excel changes like:
1-3
becomes
Jan-3
I can easily overcome this issue by using the solution outlined here: http://www.excelforum.com/excel-general/491295-opening-csv-how-to-tell-excel-string-is-not-a-date.html
csvarray.push('="'+result_item.send(column).to_s+'"')
The field in the csv becomes:
="1-3"
But would like to convert only the fields that Excel gets wrong and not all the fields.
I started by doing a:
.match(/-/)
but I am wondering if there is a better and more exclusive way to find the offending fields.
Any ideas?
Ruby 1.8.7, Rails 3.2.12
EDIT: Combining both #Agis and #Mori's answers seems to cover most of the examples I have come across:
def col_is_date?(value)
(!!(Date.parse(value) rescue nil)) || ((value =~ /\A\d{1,2}-\d{1,2}\z/) === 0)
end
I am not sure who to award the "correct" answer to...
EDIT 2: regarding the two correct answers I defer to: https://meta.stackexchange.com/questions/196341/combination-of-two-answers-is-the-correct-answer
def col_is_date?(value)
!!(Date.parse(value) rescue nil)
end
You should be explicit and specify what values you want to allow:
regexp = /\A\d{1,2}-\d{1,2}\z/
'1-1' =~ regexp # => 0
'Jan-1' =~ regexp # => nil
This regular expression will match everything that starts with one to two digits, followed by a -, followed (and ending) with one to two digits.
Per my edits I found the combination of the two answers to be what I needed or "correct" and again referring to this https://meta.stackexchange.com/questions/196341/combination-of-two-answers-is-the-correct-answer I believe the next step is to answer my own question with the combined answer.
def col_is_date?(value)
(!!(Date.parse(value) rescue nil)) || ((value =~ /\A\d{1,2}-\d{1,2}\z/) === 0)
end

Resources