我创建了一个应该将嵌套列表转换为字典的类。以下是我的意见:
['function:and',
['variable:X', 'function:>=', 'value:13'],
['variable:Y', 'function:==', 'variable:W']]
输出应该是以下形式的字典:
{
"function": "and",
"args": [
{
"function": ">=",
"args": [
{
"variable": "X"
},
{
"value": 13
}
]
},
{
"function": "==",
"args": [
{
"variable": "Y"
},
{
"variable": "W"
}
]
}
]
}
这是接收输入列表的类,应返回所需的字典。
class Tokenizer(object):
def __init__(self, tree):
self.tree = tree
self.filter = {}
def to_dict(self, triple):
my_dict = {}
try:
first = triple[0]
second = triple[1]
third = triple[2]
except KeyError:
return
if type(second) == str and type(third) == str:
my_dict['function'] = second.split(':')[-1]
my_dict['args'] = [
{first.split(':')[0]: first.split(':')[1]},
{third.split(':')[0]: third.split(':')[1]}]
# case recursive
if type(second) == list:
my_dict['function'] = first.split(':')[-1]
my_dict['args'] = [second, third]
return my_dict
def walk(self, args):
left = self.to_dict(args[0])
right = self.to_dict(args[1])
if isinstance(left, dict):
if 'args' in left.keys():
left = self.walk(left['args'])
if isinstance(right, dict):
if 'args' in right.keys():
right = self.walk(right['args'])
args = [left, right]
return args
def run(self):
self.filter.update(self.to_dict(self.tree))
if 'args' in self.filter.keys():
self.filter['args'] = self.walk(self.filter['args'])
tree = [
'function:and',
['variable:X', 'function:>=', 'value:13'],
['variable:Y', 'function:==', 'variable:W']
]
import pprint
pp = pprint.PrettyPrinter(indent=4)
t = Tokenizer(tree)
t.run()
pp.pprint(t.filter)
我的递归方法walk
没有做它应该做的事情,而且我在递归时总是很傻,所以我无法弄清楚我做错了什么。
我得到的输出是:
{ 'args': [[None, None], [None, None]], 'function': 'and'}
答案 0 :(得分:1)
对于您的特定测试用例,您根本不需要进行递归。你可以注释掉你的电话:
import UIKit
class ViewController: UIViewController {
var laps: [String] = []
var minutes = 0
var fractions = 0
var seconds = 0
var timer = NSTimer()
var timerIsOn = false
var timerString: String = ""
@IBOutlet weak var timerLabel: UILabel!
@IBOutlet weak var lapsTable: UITableView!
@IBAction func startButton(sender: AnyObject) {
if timerIsOn == false {
fractions = 0
seconds = 0
minutes = 0
timerLabel.text = "\(minutes):\(seconds).\(fractions)"
timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
timerIsOn = true
}
}
@IBAction func stopButton(sender: AnyObject) {
timer.invalidate()
timerIsOn = false
laps.insert(timerString, atIndex: 0)
lapsTable.reloadData()
}
func updateTimer(){
fractions += 1
if fractions == 100 {
fractions = 0
seconds += 1
}
if seconds == 60 {
seconds = 0
minutes += 1
}
timerLabel.text = "\(minutes):\(seconds).\(fractions)"
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
var cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
cell.backgroundColor = self.view.backgroundColor
cell.textLabel!.text = "Solve \(indexPath.row)"
cell.detailTextLabel?.text = laps[indexPath.row]
return cell
}
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
return laps.count
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
并获得所需的输出。 如果在输入中允许嵌套函数,则只需要进行递归:
def walk(self, args):
left = self.to_dict(args[0])
right = self.to_dict(args[1])
#if isinstance(left, dict):
# if 'args' in left.keys():
# left = self.walk(left['args'])
#if isinstance(right, dict):
# if 'args' in right.keys():
# right = self.walk(right['args'])
args = [left, right]
return args
然后你必须检查一个基本情况,所以只有当你的 ['function:and',
['variable:X', 'function:>=', 'value:13'],
['function:==',
['variable:R', 'function:>=', 'value:1'],
['variable:Z', 'function:==', 'variable:K']
]
]
键的值包含未经处理的值时才进行递归:
args
然后你会得到这个:
def walk(self, args):
left = self.to_dict(args[0])
right = self.to_dict(args[1])
if isinstance(left, dict):
if 'args' in left.keys() and isinstance(left['args'][0], list):
left = self.walk(left['args'])
if isinstance(right, dict):
if 'args' in right.keys() and isinstance(right['args'][0], list):
right = self.walk(right['args'])
args = [left, right]
return args
如果您的输入列表是一个常规结构,并且在函数名字段后面始终包含参数字段,那么也会更容易。然后,您可以大大简化{ 'args': [ { 'args': [{ 'variable': 'X'}, { 'value': '13'}],
'function': '>='},
{ 'args': [ { 'args': [ { 'variable': 'R'},
{ 'value': '1'}],
'function': '>='},
{ 'args': [ { 'variable': 'Z'},
{ 'variable': 'K'}],
'function': '=='}],
'function': '=='}],
'function': 'and'}
方法。