python算法以pythonic方式完成?

wol*_*ang 5 python algorithm

给定一个输入文本数组

input_array = [
    'JUNK', 'Mon', 'JUNK', '10am', 'JUNK', '-', ' 5pm',
    '6pm', '-', '9pm', 'JUNK', 'Tue', '10am', '-', 'JUNK', '5pm'
]
Run Code Online (Sandbox Code Playgroud)

应该转换为JSON

[
  {
    "weekday_name": "monday",
    "starting_time": "10am",
    "ending_time": "5pm"
  },
  {
    "weekday_name": "monday",
    "starting_time": "6pm",
    "ending_time": "10pm"
  },
  ...
]
Run Code Online (Sandbox Code Playgroud)

虽然这是一个简单的算法,但我不得不创建通常被认为是非pythonic的临时变量.

代码有丑陋的临时变量

import pprint

input_array = ['JUNK','Mon','JUNK','10am','JUNK','-','5pm','6pm','-','9pm','JUNK','Tue','10am','-','JUNK','5pm']

business_hours = []
start_hours = None
end_hours = None
current_day = None
dash_found = False

days_of_the_week = {}
days_of_the_week['Mon'] = 'monday'
days_of_the_week['Tue'] = 'tuesday'
days_of_the_week['Wed'] = 'wednesday'
days_of_the_week['Thu'] = 'thursday'
days_of_the_week['Fri'] = 'friday'
days_of_the_week['Sat'] = 'saturday'
days_of_the_week['Sun'] = 'sunday'

for x in input_array:
    if x in days_of_the_week:
        current_day = days_of_the_week[x]     
    elif x[0].isdigit() and dash_found == False:
        starting_time = x        
    elif x == '-':
        dash_found = True    
    elif x[0].isdigit() and dash_found == True:
        ending_time = x
        business_hours.append({"weekday_name":current_day,"starting_time":starting_time,"ending_time":ending_time})
        dash_found = False


pprint.pprint(business_hours)
Run Code Online (Sandbox Code Playgroud)

我可以使我的代码不那么难看,并且无需在python中创建许多临时变量即可完成相同的操作吗?

Hol*_*olt 6

由于您的数据始终采用相同的顺序:

# Here you remove all the cells in your array which are not a day of the week
# or a time (not the call to "list" before filter object are not indexable in Python 3+)
data = list(filter(lambda x: x in days_of_the_week or x[0].isdigit(), input_array))
while data:
    # Get the first item available and remove it
    curday = days_of_the_week[data.pop(0)]
    # For each couple (start, end), add an item to business_hours
    while data and data[0][0].isdigit():
        business_hours.append({
            'weekday_name':  curday,
            'starting_time': data[0],
            'ending_time':   data[1]
        })
        data = data[2:]
Run Code Online (Sandbox Code Playgroud)

当然有很多方法可以做到这一点,curday因为你必须记住它,你可能会被这个变量所困扰(你可以使用最新的条目,business_hours但它会更加丑陋,IMO).

编辑:有人建议编辑说list没有必要.因为我不知道你使用的是哪个版本的Python,我认为python 3.0,在这种情况下list是强制性的(filter是那种generator在python 3.0,所以他们不能被索引).如果您正在使用python 2.0,list可能不是强制性的.


为了它的乐趣,这里是一个使用reduce的单线程(我必须告诉你不要这样做吗?):

from functools import reduce # Okay, okay, 2 lines!
reduce (lambda r, x: r + [{'weekday_name': days_of_the_week[x]}] if x in days_of_the_week 
                     else r + [{'weekday_name': r[-1]['weekday_name'], 'starting_time': x}] if len(r[-1]) == 3 
                     else (r[-1].update({'starting_time': x}), r)[1] if len(r[-1]) == 1 
                     else (r[-1].update({'ending_time': x}), r)[1], 
        filter(lambda x: x in days_of_the_week or x[0].isdigit(), input_array), [])
Run Code Online (Sandbox Code Playgroud)

  • @GyörgySolymosi我理解你的观点,但我不认为它适用于此:第一行(使用lambda)很容易理解(你在特定条件下过滤),2个循环可能需要一个注释但没有复杂在这里,只要你知道你正在使用哪个数据结构和python切片(我认为这是任何python用户的要求).而且(当然),后来使用`reduce`的例子是纯粹的"笑话".无论如何,这是我自己的看法,这是一个长期的辩论主题;) (2认同)