Created
January 10, 2018 08:00
-
-
Save oldrev/c8e59f3fba8f445eab59ebe580c0864b to your computer and use it in GitHub Desktop.
Typescript Expression Tree to Lambda Expression
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function visitAndExpression(exprNode: any): any { | |
const conditions = exprNode.expressions.map(function (expr: any) { return visitExpression(expr) }) | |
return function (it: any) { return conditions.every(function (c: any) { return c(it) }) } | |
} | |
function visitOrExpression(exprNode: any): any { | |
const conditions = exprNode.expressions.map(function (expr: any) { return visitExpression(expr) }) | |
return function (it: any) { return conditions.some(function (c: any) { return c(it) }) } | |
} | |
function visitNotExpression(exprNode: any): any { | |
return function (it: any) { | |
const condition = visitExpression(exprNode.subexpression) | |
return !condition(it) | |
} | |
} | |
function visitUnaryExpression(exprNode: any): any { | |
switch (exprNode['node']) { | |
case 'and': return visitAndExpression(exprNode) | |
case 'or': return visitOrExpression(exprNode) | |
case 'not': return visitNotExpression(exprNode) | |
default: break; | |
} | |
} | |
function visitBinaryExpression(exprNode: any): any { | |
switch (exprNode.node) { | |
case 'eq': return visitEqExpression(exprNode); | |
case 'ne': return visitNeExpression(exprNode); | |
default: break; | |
} | |
} | |
function visitExpression(exprNode: any): any { | |
switch (exprNode.node) { | |
case 'and': return visitUnaryExpression(exprNode) | |
case 'or': return visitUnaryExpression(exprNode) | |
case 'not': return visitUnaryExpression(exprNode) | |
case 'eq': return visitBinaryExpression(exprNode) | |
case 'ne': return visitBinaryExpression(exprNode) | |
} | |
} | |
function visitPropertyValueExpression(propertyName: string) { | |
return function (it: any) { return it[propertyName] } | |
} | |
function visitEqExpression(exprNode: any) { | |
let leftFunc = visitPropertyValueExpression(exprNode.property) | |
let rightValue = visitConstantExpression(exprNode.subexpression) | |
return function (it: any) { return leftFunc(it) == rightValue } //TODO 这里根据字符串或者数字分开处理 | |
} | |
function visitNeExpression(exprNode: any) { | |
let leftFunc = visitPropertyValueExpression(exprNode.property) | |
let rightValue = visitConstantExpression(exprNode.subexpression) | |
return function (it: any) { return leftFunc(it) != rightValue } | |
} | |
function visitConstantExpression(exprNode: any): any { | |
return exprNode.value | |
} | |
function filter(source: any[], exprNode: any): any { | |
const expr = visitExpression(exprNode) | |
return source.filter(expr) | |
} | |
const targetList = [ | |
{ name: 'Bill', age: 30, gender: 'm' }, | |
{ name: 'Anne', age: 28, gender: 'f' }, | |
] | |
//表示 !(it.name === 'Bill') && it.gender === 'm' | |
const yourExpr = { | |
node: 'and', | |
expressions: [ | |
{ | |
node: 'not', | |
subexpression: { | |
node: 'eq', | |
property: 'age', | |
subexpression: { | |
node: 'constant', | |
value: 28 | |
} | |
} | |
}, | |
{ | |
node: 'eq', | |
property: 'gender', | |
subexpression: { | |
node: 'constant', | |
value: 'm' | |
} | |
} | |
] | |
} | |
const expr2 = { | |
node: 'and', | |
expressions: [ | |
{ | |
node: 'eq', | |
property: 'age', | |
subexpression: { | |
node: 'constant', | |
value: 28 | |
} | |
}, | |
{ | |
node: 'eq', | |
property: 'gender', | |
subexpression: { | |
node: 'constant', | |
value: 'f' | |
} | |
} | |
] | |
} | |
const results = filter(targetList, yourExpr) | |
console.log(results) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment