jmespath / jmespath/jmespath.jep
Function proposal - groupBy()
- Dominant language
- Python
- Stars
- 10
- Forks
- 3
- PR merge metrics
- No merged PRs in 30d
Description
Given an array of objects, group the array on a key or expression such that:
```javascript
// Object array with string
let returnValue = await applyFunction('fn:jmespath', 'groupBy(@, `a`)', [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
{ a: 2, b: 2 },
{ a: null, b: 999 },
]);
expect(returnValue).toStrictEqual({
1: [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
],
2: [{ a: 2, b: 2 }],
null: [{ a: null, b: 999 }],
});
// Object array with expression reference
returnValue = await applyFunction('fn:jmespath', 'groupBy(@, &a)', [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
{ a: 2, b: 2 },
{ a: null, b: 999 },
]);
expect(returnValue).toStrictEqual({
1: [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
],
2: [{ a: 2, b: 2 }],
null: [{ a: null, b: 999 }],
});
// Object array with inconsistent schema
returnValue = await applyFunction('fn:jmespath', 'groupBy(@, &a)', [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
{ b: 4 },
{ a: null, b: 999 },
]);
expect(returnValue).toStrictEqual({
1: [
{ a: 1, b: 2 },
{ a: 1, b: 3 },
],
null: [{ b: 4 }, { a: null, b: 999 }],
});
// Inconsistent array member types
try {
returnValue = await applyFunction('fn:jmespath', 'groupBy(@, &a)', [
{ a: 1, b: 2 },
`{ a: 1, b: 3 }`,
{ b: 4 },
1234,
]);
} catch (error) {
expect(error.message).toEqualText(
'TypeError: unexpected type. Expected Array but received Array',
);
}
```
In javascript (typescript) this might implemented as follows something like:
```javascript
registerFunction(
'groupBy',
function (this: any, [memberList, exprefNode]: [JSONObject[], ExpressionNodeTree | string]) {
if (!this._interpreter) return {};
if (typeof exprefNode === 'string') {
return memberList.reduce((grouped, member) => {
if (exprefNode in member) {
const key = member[exprefNode] as string;
const currentMembers = (grouped[key] as any[]) || [];
grouped[key] = [...currentMembers, member];
}
return grouped;
}, {});
}
const interpreter = this._interpreter;
const requiredType = Array.from(new Set(memberList.map(member => this.getTypeName(member))));
const onlyObjects = requiredType.every(x => x === TYPE_OBJECT);
if (!onlyObjects) {
throw new Error(
`TypeError: unexpected type. Expected Array but received Array<${requiredType
.map(type => this.TYPE_NAME_TABLE[type])
.join(' | ')}>`,
);
}
return memberList.reduce((grouped, member) => {
const key = interpreter.visit(exprefNode, member) as string;
const currentMembers = (grouped[key] as any[]) || [];
grouped[key] = [...currentMembers, member];
return grouped;
}, {});
},
[{ types: [TYPE_ARRAY] }, { types: [TYPE_EXPREF, TYPE_STRING] }],
);
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.