Skip to content

Commit f048da8

Browse files
committed
Добавлена функция functional::takewhile
1 parent 890d2aa commit f048da8

File tree

4 files changed

+80
-10
lines changed

4 files changed

+80
-10
lines changed

src/main/java/com/annimon/ownlang/lib/modules/functional.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ public void init() {
2222
Functions.set("map", new functional_map());
2323
Functions.set("flatmap", new functional_flatmap());
2424
Functions.set("reduce", new functional_reduce());
25-
Functions.set("filter", new functional_filter());
25+
Functions.set("filter", new functional_filter(false));
2626
Functions.set("sortby", new functional_sortby());
27-
27+
Functions.set("takewhile", new functional_filter(true));
28+
2829
Functions.set("chain", new functional_chain());
2930
Functions.set("combine", new functional_combine());
3031
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.annimon.ownlang.lib.modules.functions;
2+
3+
import com.annimon.ownlang.exceptions.TypeException;
4+
import com.annimon.ownlang.lib.*;
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
8+
import java.util.Map;
9+
10+
public final class functional_filter implements Function {
11+
12+
@Override
13+
public Value execute(Value... args) {
14+
Arguments.check(2, args.length);
15+
if (args[1].type() != Types.FUNCTION) {
16+
throw new TypeException("Function expected in second argument");
17+
}
18+
19+
final Value container = args[0];
20+
final Function consumer = ((FunctionValue) args[1]).getValue();
21+
if (container.type() == Types.ARRAY) {
22+
return filterArray((ArrayValue) container, consumer);
23+
}
24+
25+
if (container.type() == Types.MAP) {
26+
return filterMap((MapValue) container, consumer);
27+
}
28+
29+
throw new TypeException("Invalid first argument. Array or map expected");
30+
}
31+
32+
private Value filterArray(ArrayValue array, Function predicate) {
33+
final int size = array.size();
34+
final List<Value> values = new ArrayList<Value>(size);
35+
for (Value value : array) {
36+
if (predicate.execute(value) != NumberValue.ZERO) {
37+
values.add(value);
38+
}
39+
}
40+
final int newSize = values.size();
41+
return new ArrayValue(values.toArray(new Value[newSize]));
42+
}
43+
44+
private Value filterMap(MapValue map, Function predicate) {
45+
final MapValue result = new MapValue(map.size());
46+
for (Map.Entry<Value, Value> element : map) {
47+
if (predicate.execute(element.getKey(), element.getValue()) != NumberValue.ZERO) {
48+
result.set(element.getKey(), element.getValue());
49+
}
50+
}
51+
return result;
52+
}
53+
}

src/main/java/com/annimon/ownlang/lib/modules/functions/functional_filter.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
import com.annimon.ownlang.lib.*;
55
import java.util.ArrayList;
66
import java.util.List;
7-
87
import java.util.Map;
98

109
public final class functional_filter implements Function {
1110

11+
private final boolean takeWhile;
12+
13+
public functional_filter(boolean takeWhile) {
14+
this.takeWhile = takeWhile;
15+
}
16+
1217
@Override
1318
public Value execute(Value... args) {
1419
Arguments.check(2, args.length);
@@ -17,36 +22,36 @@ public Value execute(Value... args) {
1722
}
1823

1924
final Value container = args[0];
20-
final Function consumer = ((FunctionValue) args[1]).getValue();
25+
final Function predicate = ((FunctionValue) args[1]).getValue();
2126
if (container.type() == Types.ARRAY) {
22-
return filterArray((ArrayValue) container, consumer);
27+
return filterArray((ArrayValue) container, predicate, takeWhile);
2328
}
2429

2530
if (container.type() == Types.MAP) {
26-
return filterMap((MapValue) container, consumer);
31+
return filterMap((MapValue) container, predicate, takeWhile);
2732
}
2833

2934
throw new TypeException("Invalid first argument. Array or map expected");
3035
}
3136

32-
private Value filterArray(ArrayValue array, Function predicate) {
37+
private Value filterArray(ArrayValue array, Function predicate, boolean takeWhile) {
3338
final int size = array.size();
3439
final List<Value> values = new ArrayList<Value>(size);
3540
for (Value value : array) {
3641
if (predicate.execute(value) != NumberValue.ZERO) {
3742
values.add(value);
38-
}
43+
} else if (takeWhile) break;
3944
}
4045
final int newSize = values.size();
4146
return new ArrayValue(values.toArray(new Value[newSize]));
4247
}
4348

44-
private Value filterMap(MapValue map, Function predicate) {
49+
private Value filterMap(MapValue map, Function predicate, boolean takeWhile) {
4550
final MapValue result = new MapValue(map.size());
4651
for (Map.Entry<Value, Value> element : map) {
4752
if (predicate.execute(element.getKey(), element.getValue()) != NumberValue.ZERO) {
4853
result.set(element.getKey(), element.getValue());
49-
}
54+
} else if (takeWhile) break;
5055
}
5156
return result;
5257
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use "functional"
2+
3+
def testFunctionalChain() {
4+
data = [1,2,3,4,5,6,7]
5+
result = chain(data,
6+
::filter, def(x) = x <= 4,
7+
::sortby, def(x) = -x,
8+
::map, def(x) = x * 2,
9+
)
10+
assertEquals([8,6,4,2], result)
11+
}

0 commit comments

Comments
 (0)