Skip to content

Commit

Permalink
Remove recursions from array:flatten function
Browse files Browse the repository at this point in the history
  • Loading branch information
DrRataplan committed Aug 16, 2023
1 parent ddc694a commit 45de3dc
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 9 deletions.
17 changes: 8 additions & 9 deletions src/expressions/functions/builtInFunctions_arrays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,25 +460,24 @@ const arraySort: FunctionDefinitionType = (
});
};

function flattenItem(flatteneditems: ISequence, item: Value): ISequence {
function flattenItem(item: Value): ISequence {
if (isSubtypeOf(item.type, ValueType.ARRAY)) {
return (item as ArrayValue).members.reduce(
(flatteneditemsOfMember, member) =>
member().mapAll((allValues) =>
allValues.reduce(flattenItem, flatteneditemsOfMember)
),
flatteneditems
const arrayItem = item as ArrayValue;
return concatSequences(
arrayItem.members.map((member) =>
member().mapAll((subItems) => concatSequences(subItems.map(flattenItem)))
)
);
}
return concatSequences([flatteneditems, sequenceFactory.singleton(item)]);
return sequenceFactory.singleton(item);
}
const arrayFlatten: FunctionDefinitionType = (
_dynamicContext,
_executionParameters,
_staticContext,
itemSequence
) => {
return itemSequence.mapAll((items) => items.reduce(flattenItem, sequenceFactory.empty()));
return itemSequence.mapAll((items) => concatSequences(items.map(flattenItem)));
};

const declarations: BuiltinDeclarationType[] = [
Expand Down
16 changes: 16 additions & 0 deletions test/specs/parsing/arrays/arrayFunctions.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
evaluateXPath,
evaluateXPathToArray,
evaluateXPathToBoolean,
evaluateXPathToNumber,
evaluateXPathToNumbers,
evaluateXPathToString,
evaluateXPathToStrings,
Expand Down Expand Up @@ -433,6 +434,21 @@ describe('functions over arrays', () => {
evaluateXPathToStrings('array:flatten(["a", ["b", "c"], "d"])', documentNode),
['a', 'b', 'c', 'd']
));

it('can flatten long arrays', () =>
chai.assert.equal(
evaluateXPathToNumber('array:flatten(array{1 to 20000}) => count()', documentNode),
20000
));

it('can flatten deep arrays', () =>
chai.assert.equal(
evaluateXPathToNumber(
'(1 to 200) => fold-left([1], function ($accum, $item) {[$accum, $item]}) => array:flatten() => count()',
documentNode
),
201
));
});

describe('atomizing arrays', () => {
Expand Down

0 comments on commit 45de3dc

Please sign in to comment.