@@ -613,46 +613,15 @@ export class Interpreter {
613613
614614 if ( operand instanceof ArrayValue ) {
615615 switch ( filterName ) {
616- case "selectattr" : {
617- if ( operand . value . some ( ( x ) => ! ( x instanceof ObjectValue ) ) ) {
618- throw new Error ( "`selectattr` can only be applied to array of objects" ) ;
619- }
620- if ( filter . args . some ( ( x ) => x . type !== "StringLiteral" ) ) {
621- throw new Error ( "arguments of `selectattr` must be strings" ) ;
622- }
623-
624- const [ attr , testName , value ] = filter . args . map ( ( x ) => this . evaluate ( x , environment ) ) as StringValue [ ] ;
625-
626- let testFunction : ( ...x : AnyRuntimeValue [ ] ) => boolean ;
627- if ( testName ) {
628- // Get the test function from the environment
629- const test = environment . tests . get ( testName . value ) ;
630- if ( ! test ) {
631- throw new Error ( `Unknown test: ${ testName . value } ` ) ;
632- }
633- testFunction = test ;
634- } else {
635- // Default to truthiness of first argument
636- testFunction = ( ...x : AnyRuntimeValue [ ] ) => x [ 0 ] . __bool__ ( ) . value ;
637- }
638-
639- // Filter the array using the test function
640- const filtered = ( operand . value as ObjectValue [ ] ) . filter ( ( item ) => {
641- const a = item . value . get ( attr . value ) ;
642- if ( a ) {
643- return testFunction ( a , value ) ;
644- }
645- return false ;
646- } ) ;
647-
648- return new ArrayValue ( filtered ) ;
649- }
616+ case "selectattr" :
650617 case "rejectattr" : {
618+ const select = filterName === "selectattr" ;
619+
651620 if ( operand . value . some ( ( x ) => ! ( x instanceof ObjectValue ) ) ) {
652- throw new Error ( "`rejectattr` can only be applied to array of objects" ) ;
621+ throw new Error ( `\` ${ filterName } \` can only be applied to array of objects` ) ;
653622 }
654623 if ( filter . args . some ( ( x ) => x . type !== "StringLiteral" ) ) {
655- throw new Error ( " arguments of `rejectattr ` must be strings" ) ;
624+ throw new Error ( ` arguments of \` ${ filterName } \ ` must be strings` ) ;
656625 }
657626
658627 const [ attr , testName , value ] = filter . args . map ( ( x ) => this . evaluate ( x , environment ) ) as StringValue [ ] ;
@@ -673,10 +642,8 @@ export class Interpreter {
673642 // Filter the array using the test function
674643 const filtered = ( operand . value as ObjectValue [ ] ) . filter ( ( item ) => {
675644 const a = item . value . get ( attr . value ) ;
676- if ( a ) {
677- return ! testFunction ( a , value ) ;
678- }
679- return true ;
645+ const result = a ? testFunction ( a , value ) : false ;
646+ return select ? result : ! result ;
680647 } ) ;
681648
682649 return new ArrayValue ( filtered ) ;
0 commit comments