Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
189 views
in Technique[技术] by (71.8m points)

python 3.x - Is there a good way to shorten these if/elif/else statements?

I am an amateur when it comes to programming and understanding the concepts, so I wanted to know whether or not I could shorten this code down. I have heard about the phrase "spaghetti code" before, and I am trying my best not to fall down that path of bad, messy code. Here's my code:

if amount[-1] == 's' and amount[:-1].isnumeric():
    amount = int(amount[:-1])
    unit = "seconds"
elif amount[-1] == 'm' and amount[:-1].isnumeric():
    amount = int(amount[:-1])*60
    unit = "minutes"
elif amount[-2:] == 'hr' and amount[:-2].isnumeric():
    amount = int(amount[:-1])*60*60
    unit = "hours"
elif amount[-1] == 'd' and amount[:-1].isnumeric():
    amount = int(amount[:-1])*60*60*24
    unit = "days"
elif reason != None:
    reason = f'{amount} {reason}'
else:
    reason = f'{amount}'

The user inputs an amount of time (ex: 6hr, 34m, 2s, or 1d) and is used later in the program. Is there a good way to trim this down?

question from:https://stackoverflow.com/questions/65865746/is-there-a-good-way-to-shorten-these-if-elif-else-statements

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

We've all been there, I believe one good way to get better at this would be first to analyze the problem and find a pattern in the data your program expects. One pattern that's noticeable is:

  • The user always inputs a string (because "22hr, 2m, 4d" are alpha-numeric values)
  • A valid input would always have numbers and alphabets (hr, m, s, d) in it
  • A valid input would always start with a number

These are some of the patterns you can bring out from the problem. Now for the solution:

  • validate your input starts with a number ( you can make other validations at the top)
if amount[0].isnumeric():
  # remaining logic here

This eliminates the need to keep repeating yourself on every elif

  • Next, set a list of dictionaries of allowed alphabetical characters, their unit and their numerical value
timeOptions = [
   { 'shortcode': 'm', 'unit': 'minutes', 'value': 60 },
   { 'shortcode': 's', 'unit': 'seconds', 'value': 1 },
   { 'shortcode': 'hr', 'unit': 'hours', 'value': 3600 },
   { 'shortcode': 'd', 'unit': 'days', 'value': 86400 },
]
  • Next filter the numerical values from the string
number = ''.join(filter(str.isdigit, amount))
  • Filter the alphabet values from the string
shortcode = ''.join(filter(str.isalpha, amount))

Finally from your dictionary, find the dictionary entry whose shortcode property matches the unit from the user's input. For this, you can use list comprehension

timeValue = [x for x in li if x["shortcode"] == shortcode ][0] # refactor to check list length before attempting to access the first item

finally, you can do whatever you want with the user's input and the timeValue dictionary.

amount = amount * timeValue["value"]
unit = timeValue["unit"]

The entire program might look like this:

if amount[0].isnumeric():
    timeOptions = [
      { 'shortcode': 'm', 'unit': 'minutes', 'value': 60 },
      { 'shortcode': 's', 'unit': 'seconds', 'value': 1 },
      { 'shortcode': 'hr', 'unit': 'hours', 'value': 3600 },
      { 'shortcode': 'd', 'unit': 'days', 'value': 86400 },
    ]
    number = ''.join(filter(str.isdigit, amount))
    shortcode = ''.join(filter(str.isalpha, amount))

    timeValue = [x for x in li if x["shortcode"] == shortcode ]

    if len(timeValue):
      return False
    else:
      timeValue = timeValue[0]

    amount = amount * timeValue["value"]
    unit = timeValue["unit"]
  

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...