DRYer method for if-else conditional statement? - ruby

How to write DRYer code for this in a model:
a = 10
b = 6
if a == b
a = 20
else
a
end
Basically, a remains a = 10 when a != b.

a = 10
b = 6
a = 20 if a == b
If this is in a method and you want the last value of a to be returned:
a = 10
b = 6
a == b ? a = 20 : a

Here's the third one :
You can also use short circuit operator and
a = 10
b = 6
a == b and a = 20

Related

Python 3 input and if statement

I am having some trouble with an input question that is supposed to allow the player to choose one of 5 starting races. I used the following code.
def racechoice():
players.race = input('After you get a chance to think, you choose to be...') #Here race is chosen
if players.race == "dwarf" or "Dwarf": #Race starting stats
players.race = "Dwarf"
players.level = 1
players.strength = 12
players.agility = 6
players.inteligence = 8
players.vitality = 14
elif players.race == "Orc" or "orc":
players.race = "Orc"
players.level = 1
players.strength = 14
players.agility = 10
players.inteligence = 4
players.vitality = 12
elif players.race == "elf" or "Elf":
players.level = 1
players.race = "Elf"
players.strength = 8
players.agility = 13
players.inteligence = 12
players.vitality = 7
elif players.race == "Human" or "human":
players.level = 1
players.race = "Human"
players.strength = 10
players.agility = 10
players.inteligence = 10
players.vitality = 10
elif players.race == "gnome" or "Gnome":
players.race = "Gnome"
players.strength = 5
players.agility = 11
players.intelligence = 17
players.vitality = 7
When called to display the player's stats:
def stats():
print(players.name)
print(players.race)
print("Level: "+ str(players.level) +" Strength: "+ str(players.strength) +" Agility: " + str(players.agility) +" Inteligence: "+ str(players.inteligence) +" Vitality: "+ str(players.vitality))
It comes back as Dwarf with Dwarf stats no matter what the player chooses. I'm new-ish to Python and was wondering, did I not use the if/elif statement(s) correctly?
ex) After you get a chance to think, you choose to be...Orc
Ecep
Dwarf
Level: 1 Strength: 12 Agility: 6 Inteligence: 8 Vitality: 14
There is a problem, you should do:
if players.race == "dwarf" or "players.race == Dwarf":
But even better, change your conditions to:
elif players.race.lower() == "orc":
It is also recommended that you use a class to encapsulate functionality, for example:
class Player(object):
def __init__(self, race, level, strength, agility, inteligence, vitality):
self.race = race
self.level = level
self.strength = strength
self.agility = agility
self.inteligence = inteligence
self.vitality = vitality
player = Player('Dwarf', 1, 12, 6, 8, 14)
then your racechoice function will look so:
def racechoice():
race = input('After you get a chance to think, you choose to be...')
if race.lower() == 'dwarf':
player = Player('Dwarf', 1, 12, 6, 8, 14)
elif race.lower() == 'orc':
player = Player('Orc', 1, 14, 10, 4, 12)
...
return player
You can't use or in that way. All your if/elif statements should be of the form:
if players.race == "dwarf" or players.race == "Dwarf":
"Dwarf" all by itself is considered True by Python and empty strings "" are considered False, so your first if always succeeds.

(hadoop.pig) multiple counts in single table

So, I have a data that has two values, string, and a number.
data(string:chararray, number:int)
and I am counting in 5 different rules,
1: int being 0~1.
2: int being 1~2.
~
5: int being 4~5.
So I was able to count them individually,
zero_to_one = filter avg_user by average_stars >= 0 and average_stars <= 1;
A = GROUP zero_to_one ALL;
zto_count = FOREACH A GENERATE COUNT(zero_to_one);
one_to_two = filter avg_user by average_stars > 1 and average_stars <= 2;
B = GROUP one_to_two ALL;
ott_count = FOREACH B GENERATE COUNT(one_to_two);
two_to_three = filter avg_user by average_stars > 2 and average_stars <= 3;
C = GROUP two_to_three ALL;
ttt_count = FOREACH C GENERATE COUNT( two_to_three);
three_to_four = filter avg_user by average_stars > 3 and average_stars <= 4;
D = GROUP three_to_four ALL;
ttf_count = FOREACH D GENERATE COUNT( three_to_four);
four_to_five = filter avg_user by average_stars > 4 and average_stars <= 5;
E = GROUP four_to_five ALL;
ftf_count = FOREACH E GENERATE COUNT( four_to_five);
So, this can be done, but
this only results in 5 individual table.
I want to see if there is any way (is ok to be fancy, I love fancy stuff)
T can make the result in single table.
Which means if
zto_count = 1
ott_count = 3
. = 2
. = 3
. = 5
then the table will be {1,3,2,3,5}
It just is easy to parse data, and organize them that way.
Is there any ways?
Using this as input:
foo 2
foo 3
foo 2
foo 3
foo 5
foo 4
foo 0
foo 4
foo 4
foo 5
foo 1
foo 5
(0 and 1 each appear once, 2 and 3 each appear twice, 4 and 5 each appear thrice)
This script:
A = LOAD 'myData' USING PigStorage(' ') AS (name: chararray, number: int);
B = FOREACH (GROUP A BY number) GENERATE group AS number, COUNT(A) AS count ;
C = FOREACH (GROUP B ALL) {
zto = FOREACH B GENERATE (number==0?count:0) + (number==1?count:0) ;
ott = FOREACH B GENERATE (number==1?count:0) + (number==2?count:0) ;
ttt = FOREACH B GENERATE (number==2?count:0) + (number==3?count:0) ;
ttf = FOREACH B GENERATE (number==3?count:0) + (number==4?count:0) ;
ftf = FOREACH B GENERATE (number==4?count:0) + (number==5?count:0) ;
GENERATE SUM(zto) AS zto,
SUM(ott) AS ott,
SUM(ttt) AS ttt,
SUM(ttf) AS ttf,
SUM(ftf) AS ftf ;
}
Produces this output:
C: {zto: long,ott: long,ttt: long,ttf: long,ftf: long}
(2,3,4,5,6)
The number of FOREACHs in C shouldn't really matter because C is going to only have 5 elements at most, but if it is then then they can be put together like this:
C = FOREACH (GROUP B ALL) {
total = FOREACH B GENERATE (number==0?count:0) + (number==1?count:0) AS zto,
(number==1?count:0) + (number==2?count:0) AS ott,
(number==2?count:0) + (number==3?count:0) AS ttt,
(number==3?count:0) + (number==4?count:0) AS ttf,
(number==4?count:0) + (number==5?count:0) AS ftf ;
GENERATE SUM(total.zto) AS zto,
SUM(total.ott) AS ott,
SUM(total.ttt) AS ttt,
SUM(total.ttf) AS ttf,
SUM(total.ftf) AS ftf ;
}

vbscript error: expected statement (do until)

ok so im trying to do an assignment and i have written this code but it has errors, and i cant see why.
its saying expected statement, and im looking over it and i cant find what the problem is. Would be amazing if someone could shed some light on the error and possibly help me out.
here is the do until statement:
Sub btnTransformY_onclick()
Do Until r = 4 And n = 3
Do Until m = 1 To 8
Change(r,c) = (transformationY(r,1) * meh(1, m)) + transformationY(r, 2) * meh(2,m) + TransformationY(r,3) * meh(3,m)
m = m + 1
Next
c = c + 1
If c = 8 Then r = r + 1 And c = 1
Next
End Sub
unfortunately this hasnt worked, although it does seem to be the Do Until m = 1 To 8
does anyone know if to is valid syntax for a do until loop?
I reckon you want something on these lines, except I suspect you want two Next loops for r and n rather than one Do Until.
Sub btnTransformY_onclick()
r = 0
n = 0
Do Until r = 4 And n = 3
For m = 1 To 8
Change(r,c) = (transformationY(r,1) * meh(1, m)) + transformationY(r, 2) * meh(2,m) + TransformationY(r,3) * meh(3,m)
''m = m + 1
Next
c = c + 1
If c = 8 Then
r = r + 1
c = 1
''Where does n get counted up?
End If
Loop
End Sub
Next is for for loops, to close a do loop use loop:
do until ..
...
loop
Also
if c = 8 then r = r + 1 and c = 1
Is a bitwise comparison (bits of LHS anded with RHS) which is probably not what you want, so instead;
if c = 8 then
r = r + 1
c = 1
end if

Assign the first non-zero value

Let's say I have the following variables defined:
a = 6
b = 4
c = 0
I want to assign the first non-zero value to another variable, but in reverse order (c -> b -> a). I originally tried d = c || b || a, but that still resulted in 0. Is there a one-liner way of doing this?
Use detect
[c,b,a].detect { |i| i > 0 }
[c,b,a].select { |i| i > 0 }.first => 4

ruby - simplify string multiply concatenation

s is a string, This seems very long-winded - how can i simplify this? :
if x === 2
z = s
elsif x === 3
z = s+s
elsif x === 4
z = s+s+s
elsif x === 5
z = s+s+s+s
elsif x === 6
z = s+s+s+s+s
Thanks
Something like this is the simplest and works (as seen on ideone.com):
puts 'Hello' * 3 # HelloHelloHello
s = 'Go'
x = 4
z = s * (x - 1)
puts z # GoGoGo
API links
ruby-doc.org - String: str * integer => new_str
Copy—Returns a new String containing integer copies of the receiver.
"Ho! " * 3 #=> "Ho! Ho! Ho! "
z=''
(x-1).times do
z+=s
end
Pseudo code (not ruby)
if 1 < int(x) < 7 then
z = (x-1)*s
For example for a rating system up to 5 stars you can use something like this:
def rating_to_star(rating)
'star' * rating.to_i + 'empty_star' * (5 - rating.to_i)
end

Resources