Add join function to merge 2 lists by a join field #316

This commit is contained in:
Francis Dong
2021-09-23 15:50:40 +08:00
committed by dxfeng10
parent ef128e8f13
commit f4966b59a4
2 changed files with 89 additions and 7 deletions

View File

@@ -57,6 +57,7 @@ public class ListFunc implements IFunc {
FuncExecutor.register(NAME_SPACE_PREFIX + "list.expand", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "list.merge", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "list.extract", this);
FuncExecutor.register(NAME_SPACE_PREFIX + "list.join", this);
}
/**
@@ -108,7 +109,7 @@ public class ListFunc implements IFunc {
if (data == null || data.size() == 0) {
return result;
}
if (fields.length == 0) {
if (fields == null || fields.length == 0) {
return data;
}
for (Map<String, Object> m : data) {
@@ -121,4 +122,44 @@ public class ListFunc implements IFunc {
return result;
}
/**
* Merge fields of source list to destination list join by the join field
*
* @param dest destination list
* @param src source list
* @param joinField join field
* @param fields fields which will be merge to destination list, all fields
* will be merged if it is null
* @return
*/
public List<Map<String, Object>> join(List<Map<String, Object>> dest, List<Map<String, Object>> src,
String joinField, String... fields) {
if (dest == null || dest.size() == 0 || src == null || src.size() == 0) {
return dest;
}
Map<String, Map<String, Object>> index = new HashMap<>();
for (Map<String, Object> record : dest) {
if (record.get(joinField) != null) {
index.put(record.get(joinField).toString(), record);
}
}
for (Map<String, Object> m : src) {
if (m.get(joinField) == null) {
continue;
}
Map<String, Object> record = index.get(m.get(joinField).toString());
if (fields == null || fields.length == 0) {
record.putAll(m);
} else {
for (String field : fields) {
record.put(field, m.get(field));
}
}
}
return dest;
}
}

View File

@@ -26,6 +26,8 @@ import java.util.Map;
import org.junit.jupiter.api.Test;
import org.noear.snack.ONode;
import com.alibaba.fastjson.JSON;
import we.fizz.input.PathMapping;
/**
@@ -44,7 +46,7 @@ class ListFuncTests {
m.put(key, value);
return m;
}
private Map<String, Object> createRecord2(int index) {
Map<String, Object> m = new HashMap<>();
m.put("a", "a" + index);
@@ -81,8 +83,7 @@ class ListFuncTests {
assertEquals("a2", ((Map<String, Object>) result.get(1)).get("a").toString());
assertEquals("a4", ((Map<String, Object>) result.get(3)).get("a").toString());
}
@Test
void testMerge() {
List<Object> subList1 = new ArrayList<>();
@@ -95,7 +96,6 @@ class ListFuncTests {
subList2.add(createRecord("a", "a5"));
subList2.add(createRecord("a", "a6"));
ONode ctxNode = ONode.load(new HashMap());
PathMapping.setByPath(ctxNode, "test.data1", subList1, true);
PathMapping.setByPath(ctxNode, "test.data2", subList2, true);
@@ -106,7 +106,7 @@ class ListFuncTests {
assertEquals("a2", ((Map<String, Object>) result.get(1)).get("a").toString());
assertEquals("a4", ((Map<String, Object>) result.get(3)).get("a").toString());
}
@Test
void testExtract() {
List<Object> subList1 = new ArrayList<>();
@@ -116,7 +116,6 @@ class ListFuncTests {
subList1.add(createRecord2(4));
subList1.add(createRecord2(5));
ONode ctxNode = ONode.load(new HashMap());
PathMapping.setByPath(ctxNode, "test.data", subList1, true);
@@ -130,4 +129,46 @@ class ListFuncTests {
// System.out.println(result);
}
private Map<String, Object> createRecord3(int index, boolean isDest) {
Map<String, Object> m = new HashMap<>();
m.put("a", "a" + index);
String s = isDest ? "" + index : index + "-abc";
m.put("b", "b" + s);
m.put("c", "c" + s);
if (!isDest) {
m.put("d", "d" + s);
m.put("e", "e" + s);
}
return m;
}
@Test
void testJoin() {
List<Object> list1 = new ArrayList<>();
list1.add(createRecord3(1, true));
list1.add(createRecord3(2, true));
list1.add(createRecord3(3, true));
list1.add(createRecord3(4, true));
list1.add(createRecord3(5, true));
List<Object> list2 = new ArrayList<>();
list2.add(createRecord3(1, false));
list2.add(createRecord3(2, false));
list2.add(createRecord3(3, false));
list2.add(createRecord3(4, false));
ONode ctxNode = ONode.load(new HashMap());
PathMapping.setByPath(ctxNode, "test.list1", list1, true);
PathMapping.setByPath(ctxNode, "test.list2", list2, true);
String funcExpression = "fn.list.join({test.list1}, {test.list2},\"a\",\"c\",\"d\")";
List<Object> result = (List<Object>) FuncExecutor.getInstance().exec(ctxNode, funcExpression);
assertEquals(5, result.size());
assertEquals("a2", ((Map<String, Object>) result.get(1)).get("a").toString());
assertEquals("d4-abc", ((Map<String, Object>) result.get(3)).get("d").toString());
// System.out.println(JSON.toJSONString(result));
}
}