Merge pull request #6204 from hsm-lv/feat-formula

feat:formula补充一些数组函数
This commit is contained in:
hsm-lv 2023-02-17 13:42:50 +08:00 committed by GitHub
commit 413d4a55d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 415 additions and 1 deletions

View File

@ -428,7 +428,22 @@ test('evalute:array:func', () => {
id: 1.1, id: 1.1,
name: 1.3 name: 1.3
} }
] ],
obj1: {
p1: 'name',
p2: 'age',
p3: 'obj',
p4: [
{
p41: 'Tom',
p42: 'Jerry'
},
{
p41: 'baidu',
p42: 'amis'
}
]
}
}; };
expect(evaluate('${COMPACT(arr1)}', data)).toMatchObject([1, 2, 3]); expect(evaluate('${COMPACT(arr1)}', data)).toMatchObject([1, 2, 3]);
@ -466,6 +481,33 @@ test('evalute:array:func', () => {
expect( expect(
evaluate('${ARRAYFILTER(arr1, item => item && item >=2)}', data) evaluate('${ARRAYFILTER(arr1, item => item && item >=2)}', data)
).toMatchObject([2, 3]); ).toMatchObject([2, 3]);
expect(evaluate('${ARRAYFINDINDEX(arr3, item => item === 2)}', data)).toBe(1);
expect(
evaluate('${ARRAYFIND(arr5, item => item.name === 1.3)}', data)
).toMatchObject({
id: 1.1,
name: 1.3
});
expect(evaluate('${ARRAYSOME(arr5, item => item.name === 1.3)}', data)).toBe(
true
);
expect(evaluate('${ARRAYEVERY(arr5, item => item.name === 1.3)}', data)).toBe(
false
);
expect(evaluate('${ARRAYINCLUDES(arr1, false)}', data)).toBe(true);
expect(evaluate('${GET(arr1, 2)}', data)).toBe(false);
expect(evaluate('${GET(arr1, 6, "not-found")}', data)).toBe('not-found');
expect(evaluate('${GET(arr5, "[2].name")}', data)).toBe(1.3);
expect(evaluate('${GET(arr5, "2.name")}', data)).toBe(1.3);
expect(evaluate('${GET(obj1, "p2")}', data)).toBe('age');
expect(evaluate('${GET(obj1, "p4.1.p42")}', data)).toBe('amis');
expect(evaluate('${GET(obj1, "p4[1].p42")}', data)).toBe('amis');
}); });
test('evalute:ISTYPE', () => { test('evalute:ISTYPE', () => {

View File

@ -863,6 +863,85 @@ DATEMODIFY(A, -2, 'month')
数据做数据过滤,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。 数据做数据过滤,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
将第二个箭头函数返回为 false 的成员过滤掉。 将第二个箭头函数返回为 false 的成员过滤掉。
### ARRAYFINDINDEX
用法:`ARRAYFINDINDEX(arr, item => item === 2)`
* `arr:Array<any>` 数组
* `iterator:Array<any>` 箭头函数
返回:`number` 结果
数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
找出第二个箭头函数返回为 true 的成员的索引。
示例:
ARRAYFINDINDEX([0, 2, false], item => item === 2) 得到 1
### ARRAYFIND
用法:`ARRAYFIND(arr, item => item === 2)`
* `arr:Array<any>` 数组
* `iterator:Array<any>` 箭头函数
返回:`any` 结果
数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
找出第二个箭头函数返回为 true 的成员。
示例:
ARRAYFIND([0, 2, false], item => item === 2) 得到 2
### ARRAYSOME
用法:`ARRAYSOME(arr, item => item === 2)`
* `arr:Array<any>` 数组
* `iterator:Array<any>` 箭头函数
返回:`boolean` 结果
数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
判断第二个箭头函数是否存在返回为 true 的成员。
示例:
ARRAYSOME([0, 2, false], item => item === 2) 得到 true
### ARRAYEVERY
用法:`ARRAYEVERY(arr, item => item === 2)`
* `arr:Array<any>` 数组
* `iterator:Array<any>` 箭头函数
返回:`boolean` 结果
数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
判断第二个箭头函数返回是否都为 true。
示例:
ARRAYEVERY([0, 2, false], item => item === 2) 得到 false
### ARRAYINCLUDES
用法:`ARRAYINCLUDES(arr, 2)`
* `arr:Array<any>` 数组
* `item:any` 元素
返回:`any` 结果
判断数据中是否存在指定元素
示例:
ARRAYINCLUDES([0, 2, false], 2) 得到 true
### COMPACT ### COMPACT
用法:`COMPACT(arr)` 用法:`COMPACT(arr)`
@ -923,6 +1002,26 @@ UNIQ([{a: '1'}, {b: '2'}, {a: '1'}] 'id')
## 其他 ## 其他
### GET
用法:`GET(arr, 2)`
* `obj:any` 对象或数组
* `path:string` 路径
* `defaultValue:any` 如果解析不到则返回该值
返回:`any` 结果
根据对象或者数组的path路径获取值。 如果解析 value 是 undefined 会以 defaultValue 取代
示例:
GET([0, 2, {name: 'amis', age: 18}], 1) 得到 2
GET([0, 2, {name: 'amis', age: 18}], '2.name') 得到 'amis'
GET({arr: [{name: 'amis', age: 18}]}, 'arr[0].name') 得到 'amis'
GET({arr: [{name: 'amis', age: 18}]}, 'arr.0.name') 得到 'amis'
GET({arr: [{name: 'amis', age: 18}]}, 'arr.1.name', 'not-found') 得到 'not-found'
### ISTYPE ### ISTYPE
用法:`ISTYPE([{a: '1'}, {b: '2'}, {a: '1'}], 'array')` 用法:`ISTYPE([{a: '1'}, {b: '2'}, {a: '1'}], 'array')`

View File

@ -1503,6 +1503,143 @@ export const doc: {
}, },
namespace: "数组" namespace: "数组"
}, },
{
name: "ARRAYFINDINDEX",
description: "数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n找出第二个箭头函数返回为 true 的成员的索引。\n\n示例\n\nARRAYFINDINDEX([0, 2, false], item => item === 2) 得到 1",
example: "ARRAYFINDINDEX(arr, item => item === 2)",
params: [
{
type: "Array<any>",
name: "arr",
description: "数组"
},
{
type: "Array<any>",
name: "iterator",
description: "箭头函数"
}
],
returns: {
type: "number",
description: "结果"
},
namespace: "数组"
},
{
name: "ARRAYFIND",
description: "数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n找出第二个箭头函数返回为 true 的成员。\n\n示例\n\nARRAYFIND([0, 2, false], item => item === 2) 得到 2",
example: "ARRAYFIND(arr, item => item === 2)",
params: [
{
type: "Array<any>",
name: "arr",
description: "数组"
},
{
type: "Array<any>",
name: "iterator",
description: "箭头函数"
}
],
returns: {
type: "any",
description: "结果"
},
namespace: "数组"
},
{
name: "ARRAYSOME",
description: "数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n判断第二个箭头函数是否存在返回为 true 的成员。\n\n示例\n\nARRAYSOME([0, 2, false], item => item === 2) 得到 true",
example: "ARRAYSOME(arr, item => item === 2)",
params: [
{
type: "Array<any>",
name: "arr",
description: "数组"
},
{
type: "Array<any>",
name: "iterator",
description: "箭头函数"
}
],
returns: {
type: "boolean",
description: "结果"
},
namespace: "数组"
},
{
name: "ARRAYEVERY",
description: "数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n判断第二个箭头函数返回是否都为 true。\n\n示例\n\nARRAYEVERY([0, 2, false], item => item === 2) 得到 false",
example: "ARRAYEVERY(arr, item => item === 2)",
params: [
{
type: "Array<any>",
name: "arr",
description: "数组"
},
{
type: "Array<any>",
name: "iterator",
description: "箭头函数"
}
],
returns: {
type: "boolean",
description: "结果"
},
namespace: "数组"
},
{
name: "ARRAYINCLUDES",
description: "判断数据中是否存在指定元素\n\n示例\n\nARRAYINCLUDES([0, 2, false], 2) 得到 true",
example: "ARRAYINCLUDES(arr, 2)",
params: [
{
type: "Array<any>",
name: "arr",
description: "数组"
},
{
type: "any",
name: "item",
description: "元素"
}
],
returns: {
type: "any",
description: "结果"
},
namespace: "数组"
},
{
name: "GET",
description: "根据对象或者数组的path路径获取值。 如果解析 value 是 undefined 会以 defaultValue 取代\n\n示例\n\nGET([0, 2, {name: 'amis', age: 18}], 1) 得到 2\nGET([0, 2, {name: 'amis', age: 18}], '2.name') 得到 'amis'\nGET({arr: [{name: 'amis', age: 18}]}, 'arr[0].name') 得到 'amis'\nGET({arr: [{name: 'amis', age: 18}]}, 'arr.0.name') 得到 'amis'\nGET({arr: [{name: 'amis', age: 18}]}, 'arr.1.name', 'not-found') 得到 'not-found'",
example: "GET(arr, 2)",
params: [
{
type: "any",
name: "obj",
description: "对象或数组"
},
{
type: "string",
name: "path",
description: "路径"
},
{
type: "any",
name: "defaultValue",
description: "如果解析不到则返回该值"
}
],
returns: {
type: "any",
description: "结果"
},
namespace: "其他"
},
{ {
name: "COMPACT", name: "COMPACT",
description: "数组过滤掉 false、null、0 和 \"\"\n\n示例\n\nCOMPACT([0, 1, false, 2, '', 3]) 得到 [1, 2, 3]", description: "数组过滤掉 false、null、0 和 \"\"\n\n示例\n\nCOMPACT([0, 1, false, 2, '', 3]) 得到 [1, 2, 3]",

View File

@ -12,6 +12,7 @@ import uniqWith from 'lodash/uniqWith';
import uniqBy from 'lodash/uniqBy'; import uniqBy from 'lodash/uniqBy';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
import isPlainObject from 'lodash/isPlainObject'; import isPlainObject from 'lodash/isPlainObject';
import get from 'lodash/get';
import {EvaluatorOptions, FilterContext, FilterMap, FunctionMap} from './types'; import {EvaluatorOptions, FilterContext, FilterMap, FunctionMap} from './types';
export class Evaluator { export class Evaluator {
@ -1841,6 +1842,141 @@ export class Evaluator {
); );
} }
/**
* 使
* true
*
*
*
* ARRAYFINDINDEX([0, 2, false], item => item === 2) 1
*
* @param {Array<any>} arr
* @param {Function<any>} iterator
* @namespace
* @example ARRAYFINDINDEX(arr, item => item === 2)
* @returns {number}
*/
fnARRAYFINDINDEX(arr: any[], iterator: any) {
if (!iterator || iterator.type !== 'anonymous_function') {
throw new Error('expected an anonymous function get ' + iterator);
}
return (Array.isArray(arr) ? arr : []).findIndex((item, index, arr) =>
this.callAnonymousFunction(iterator, [item, index, arr])
);
}
/**
* 使
* true
*
*
*
* ARRAYFIND([0, 2, false], item => item === 2) 2
*
* @param {Array<any>} arr
* @param {Function<any>} iterator
* @namespace
* @example ARRAYFIND(arr, item => item === 2)
* @returns {any}
*/
fnARRAYFIND(arr: any[], iterator: any) {
if (!iterator || iterator.type !== 'anonymous_function') {
throw new Error('expected an anonymous function get ' + iterator);
}
return (Array.isArray(arr) ? arr : []).find((item, index, arr) =>
this.callAnonymousFunction(iterator, [item, index, arr])
);
}
/**
* 使
* true
*
*
*
* ARRAYSOME([0, 2, false], item => item === 2) true
*
* @param {Array<any>} arr
* @param {Function<any>} iterator
* @namespace
* @example ARRAYSOME(arr, item => item === 2)
* @returns {boolean}
*/
fnARRAYSOME(arr: any[], iterator: any) {
if (!iterator || iterator.type !== 'anonymous_function') {
throw new Error('expected an anonymous function get ' + iterator);
}
return (Array.isArray(arr) ? arr : []).some((item, index, arr) =>
this.callAnonymousFunction(iterator, [item, index, arr])
);
}
/**
* 使
* true
*
*
*
* ARRAYEVERY([0, 2, false], item => item === 2) false
*
* @param {Array<any>} arr
* @param {Function<any>} iterator
* @namespace
* @example ARRAYEVERY(arr, item => item === 2)
* @returns {boolean}
*/
fnARRAYEVERY(arr: any[], iterator: any) {
if (!iterator || iterator.type !== 'anonymous_function') {
throw new Error('expected an anonymous function get ' + iterator);
}
return (Array.isArray(arr) ? arr : []).every((item, index, arr) =>
this.callAnonymousFunction(iterator, [item, index, arr])
);
}
/**
*
*
*
*
* ARRAYINCLUDES([0, 2, false], 2) true
*
* @param {Array<any>} arr
* @param {any} item
* @namespace
* @example ARRAYINCLUDES(arr, 2)
* @returns {any}
*/
fnARRAYINCLUDES(arr: any[], item: any) {
return (Array.isArray(arr) ? arr : []).includes(item);
}
/**
* path路径获取值 value undefined defaultValue
*
*
*
* GET([0, 2, {name: 'amis', age: 18}], 1) 2
* GET([0, 2, {name: 'amis', age: 18}], '2.name') 'amis'
* GET({arr: [{name: 'amis', age: 18}]}, 'arr[0].name') 'amis'
* GET({arr: [{name: 'amis', age: 18}]}, 'arr.0.name') 'amis'
* GET({arr: [{name: 'amis', age: 18}]}, 'arr.1.name', 'not-found') 'not-found'
*
* @param {any} obj
* @param {string} path
* @param {any} defaultValue
* @namespace
* @example GET(arr, 2)
* @returns {any}
*/
fnGET(obj: any, path: string, defaultValue?: any) {
return get(obj, path, defaultValue);
}
/** /**
* falsenull0 "" * falsenull0 ""
* *