views:

112

answers:

7

Update: the much better answer has little to do with refactoring, but has to do with setting a default for empty keys. See the first answer- thanks a lot guys!

Hi folks, how would you refactor this?

    if n=network_stats["b"]
      network_stats["b"] = n +1 
    else
      network_stats["b"]=1
    end

I have a nagging feeling this can be done in 2 lines

+3  A: 

Hi ming yeow

network_stats["b"] = (n == network_stats["b"]? (n + 1) : 1)

hope this helps

cheers

sameera

PS : This is a good site for code refactoring

http://refactormycode.com/

sameera207
Thanks a lot! =D Small correction: network_stats["b"] = ( (n=network_stats["b"]) ? (n + 1) : 1)
ming yeow
This is mostly the same code, but only in one line. There is clearer two-line solution.
lest
A: 

network_stats["b"] = (n == network_stats["b"])? n+1 : 1

christian
A: 

I'm going to assume there is a slight typo in your code, and you meant to do a comparison instead of an assignment on the first line, like this:

if n == network_stats["b"]
  network_stats["b"] = n + 1 
else
  network_stats["b"] = 1
end

I would refactor this into something like:

n == network_stats["b"] ? (network_stats["b"] = n + 1) : (network_stats["b"] = 1)

While Christians answer is more precise in terms of bytes used, I find it less readable, but that's simply personal opinion.

In case he removes his answer, it was:

network_stats["b"] = (n == network_stats["b"]) ? n + 1 : 1
Mike Trpcic
I don't think it's a typo, it's a pretty common assignation + conditional.
tokland
yup, it is not a typo. =) it is assignment + conditional
ming yeow
A: 

Hey Ming you should have known about ternary operators

I think this might help you get around

network_stats["b"] = (n == network_stats["b"]) ? n + 1 : 1

Rohit
+4  A: 
# do this when network_stats is defined
network_stats.default= 0

# to increment the network stats
network_stats["b"] += 1

for example

>> (network_stats={}).default= 0
=> 0
>> network_stats["b"] += 1
=> 1
>> network_stats
=> {"b"=>1}
gnibbler
This is a better answer than the ones that addressed your question exactly as asked...
glenn mcdonald
# do this when network_stats is defined - > do you mean when NOT defined?
ming yeow
@ming yeow, Since you didn't show how/where network_stats was initialised, perhaps it was an empty hash as in the second part of my answer, but it may have been a hash initialised from a database query for example. Whichever way it happens, once you have the hash called network_stats you set the default to 0. You only need to do this once of course which is why i suggested to do it where it is defined
gnibbler
Thanks! This is definitely a better answer than pure refactoring.
ming yeow
+5  A: 

This is a short and readable oneliner:

network_stats["b"] = (network_stats["b"] || 0) + 1

And a longer but maybe more readable and scalable (when more cases would be added in the future) version:

network_stats["b"] = case network_stats["b"]  
                       when nil then 0  
                       else network_stats["b"] + 1  
                     end  

Update: As a curiosity, this can work to:

 network_stats["b"] += 1 rescue network_stats["b"] = 1

I would not use it personally.

Jeznet
this is great, thanks! i did not know that case returns the actual item in question. Your oneliner is much more readable than the others too
ming yeow
About case: Everything is evaluated as an expression in Ruby: literal, method calls, variables. Even a control structure like case or if has a value. Use this Ruby power ;-)
Jeznet
+3  A: 

You can use ||= operator to assign value if nil, e.g.:

network_stats["b"] ||= 1

Then you are sure that network_stats["b"] has value so simple increment by 1:

network_stats["b"] += 1

Final code:

network_stats["b"] ||= 1
network_stats["b"] += 1
lest
Hey lest, thanks for the very simple, effective answer!
ming yeow