Denkan
Denkan

Reputation: 65

An alternative to many if-statements?

So I have 3 different variables.

model which is a string and defines the iPhone model.

storage which is a integer that defines the phones storage.

And finally price, which is an integer that defines the price of the phone.

Example:

model = iPhone 7
storage = 64 (GB)
price = 700 ($)

Another example:

model = iPhone 5s
storage = 16
price = 150

Now I want my program to notify me if I can make a good deal by buying and reselling, and my question is how do I do that in the most efficent way?

I know that I can use if statements, but is there any method to save me from writing alot diffrent if or elif statements?

Example:

if model == "iPhone 7" and storage == 64 and price <= 700:
print("do_something")

That's alot of code for just 1 model and storage option. If I would be using this method i'd have to write 29 more.

Upvotes: 5

Views: 8696

Answers (8)

Priyesh Kumar
Priyesh Kumar

Reputation: 2857

In this situation, I prefer dictionaries.

Create different handlers(function) that do specific task based on item and data passed. See following code :

# Different handlers, each takes keyword args and can work specific task
def fun1(**kwargs):
    print (kwargs)
    print("fun1")


def fun2(**kwargs):
    print("fun2")

def fun3(**kwargs):
    print("fun3")

def fun4(**kwargs):
    print("fun4")


# Example data. key is phoneModel_storage
a = {
    'iPhone1_64': {
        "storage": 64,
        "action": fun1,
        "price":1235
    },
    'iPhone1_32': {
        "storage": 64,
        "action": fun3,
        "price":1235
    },
    'iPhone2_16': {
        "storage": 16,
        "action": fun1,
        "price":1235
    },
    'iPhone3_32': {
        "storage": 32,
        "action": fun3,
        "price":1235
    },
    'iPhone4_128': {
        "storage": 128,
        "action": fun4,
        "price":1235
    },
}

model = "iPhone1"
storage = 64

data = a.get(model + "_" + str(storage), None)
if data:
    data['action'](**data)

Upvotes: 0

user7711283
user7711283

Reputation:

There are soooo many answers here, but still none accepted, so I will put together another one:

# Prepare a list of what you know will be good deals: 
dctGoodDeals = {}
dctGoodDeals[('iPhone 7',  64)] = 700
dctGoodDeals[('iPhone 5s', 16)] = 150

# You have got at that point in your code from somewhere: 
model = 'iPhone 7'; storage=64; price=500
# model = 'iPhone S'; storage=64; price=500

# so you can put at that point into your code following: try: if (price <= dctGoodDeals[(model, storage)]): print("do something") except: print("not yet in dctGoodDeals:", model, "with", storage, "GB")

This way you get all the printouts of what to do and save some typing effort of writing all the ifs.

Upvotes: 0

Serge
Serge

Reputation: 3775

if model, storage, price == "iPhone 7", 64, 700:
     print("do_something")

Usually I do some mini domain specific language and define prices in a string, or csc file

table =
"""Iphone 7, 64, 700
Iphone 6, 34, 500"""

lines = table.split('\n)  # for wider tables use standard csv package, but or for 3 columns
dico = dict( (r[0], r[1]), r[2]) for r in line.split(', ') for line in lines))
def good_deal(model, memory, price):
    return dico.get( (model, memory), 10000000 ) > price

Upvotes: 0

Devendra Lattu
Devendra Lattu

Reputation: 2812

Defining methods to print something

def method1():
    print "Yippee I have best iPhone 7 :)"

def method2():
    print "Oh! still it is an iPhone 7"

def method3():
    print "Yeah! I have best iPhone 5 :)"

def method4():
    print "Oh! base iPhone 5"    

Dictionary for if-else

stuff = {'iPhone 7' : {'64GB' : { '$700' : method1}, '32GB' : { '$500' : method2}}, 'iPhone 5' : {'32GB' : { '$250' : method3}, '16GB' : { '$150' : method4}}}

Access the statements like and add exception handling as needed

stuff['iPhone 7']['64GB']['$700']()

enter image description here

Reference How to avoid a lot of if else conditions

Upvotes: 0

Adam Smith
Adam Smith

Reputation: 54243

Your use case is perfect for a hashmap (dict) with something like tuples or preferably namedtuples.

from collections import namedtuple

Phone = namedtuple("Phone", "model storage price")

funcmap = {Phone("iPhone 7", 64, 700): \
             lambda p: print("Do something to ", p),
           Phone(...):  # etc
             ...,
           ... }

phone = Phone("iPhone 7", 64, 700)
f = funcmap[phone]  # maybe funcmap.get(phone, lambda _: None) in case it's new?
f(phone)

That said a decision-making algorithm seems better.

def is_good_deal(phone: Phone) -> (bool, None):
    value_dict = {Phone("iPhone 7", 64, 700): 600,
                  ...}
    try:
        return phone.value < value_dict[phone]
    except KeyError:
        # phone isn't in value_dict
        return None

Upvotes: 0

Mirek Długosz
Mirek Długosz

Reputation: 4285

If you only care about checking if particular model matches exactly data that you have, then comparing dictionaries is a way to go:

>>> reference = {"model": "iPhone 5s", "storage": 16, "price": 550}
>>> tested = {"model": "iPhone 5s", "storage": 16, "price": 550}
>>> reference == tested
True

However, this will fail if you want broader criteria, like price falling within certain range.

Then, instead of writing 29 ifs, you can store reference dictionaries in list and check if your tested model is in that list with simplest

tested in reference_list:
    # do something

Upvotes: 0

frrlod
frrlod

Reputation: 6685

You could make use of classes to minimize the code duplication:

  class Phone():
    BEST_MODELS = ["IPHONE7", "IPHONE 5S", "Galaxy S3"]
    MIN_STORAGE = 100
    MAX_STORAGE = 200
    MIN_PRICE = 1000
    MAX_PRICE = 3000
    def __init__(self, model, storage, price):
        self.model = model
        self.storage = storage
        self.price = price

    def is_good_deal(self):
        return (self.model in Phone.BEST_MODELS
            and Phone.MIN_STORAGE <= self.storage <= Phone.MAX_STORAGE
            and Phone.MIN_PRICE <= self.price <= Phone.MAX_PRICE)

p1 = Phone("IPHONE7", 150, 1700)
p2 = Phone("LG G1", 150, 700)

print(p1.is_good_deal()) # True
print(p2.is_good_deal()) # False

And if, for example, you have a collection of Phones, you can do the following:

lots_of_phones = [p1, p2]

good_deal_phones = (phone for phone in lots_of_phones if phone.is_good_deal())

Upvotes: 0

PEZO
PEZO

Reputation: 531

It's normal that you have to create a "decision rule" and somehow make it accessable by your program.

1-2 tips:

You might only specify the conditions when you have to act, and you do not specify the ones where you don't do anything.

You can use dicts instead "and"s like this which leads to less code:

deal2action = {
('iphone 7', '64', '700'):'ACT'
}

Usage:

my_deal = ('iphone 7', '64', '700')
my_action = deal2action[my_deal]

Upvotes: 1

Related Questions