Skip to content

Commit b9cc131

Browse files
authored
Merge pull request #71 from graphfoundation/3.5-unflattenMap
apoc.map.unflatten function, fixes #69
2 parents 1f51ca5 + 6106e8e commit b9cc131

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

src/main/java/apoc/map/Maps.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,36 @@ private void flattenMapRecursively(Map<String, Object> flattenedMap, Map<String,
295295
}
296296
}
297297

298+
@UserFunction
299+
@Description("apoc.map.unflatten(map) yield map - unflattens dot notated nested items in map")
300+
public Map<String,Object> unflatten( @Name( "flatMap" ) Map<String,Object> flatMap ) {
301+
Map<String,Object> unflattenedMap = new HashMap<>();
302+
303+
for ( Map.Entry<String, Object> entry : flatMap.entrySet() ) {
304+
String[] keys = entry.getKey().split( "\\." );
305+
306+
Map<String, Object> current = unflattenedMap;
307+
308+
for ( int i = 0; i < keys.length - 1; ++i ) {
309+
String key = keys[i];
310+
311+
Object temp = current.get( key );
312+
if ( temp == null ) {
313+
Map<String, Object> next = new HashMap<>();
314+
current.put( key, next );
315+
current = next;
316+
continue;
317+
}
318+
319+
current = (Map<String, Object>) temp;
320+
}
321+
322+
current.put( keys[keys.length - 1], entry.getValue() );
323+
}
324+
325+
return unflattenedMap;
326+
}
327+
298328
@UserFunction
299329
@Description("apoc.map.sortedProperties(map, ignoreCase:true) - returns a list of key/value list pairs, with pairs sorted by keys alphabetically, with optional case sensitivity")
300330
public List<List<Object>> sortedProperties(@Name("map") Map<String, Object> map, @Name(value="ignoreCase", defaultValue = "true") boolean ignoreCase) {

src/test/java/apoc/map/MapsTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import org.junit.Test;
77
import org.neo4j.graphdb.GraphDatabaseService;
88
import org.neo4j.graphdb.Node;
9+
import org.neo4j.graphdb.QueryExecutionException;
910
import org.neo4j.test.TestGraphDatabaseFactory;
1011

1112
import java.util.*;
@@ -318,6 +319,21 @@ public void testFlattenWithDelimiter() {
318319
});
319320
}
320321

322+
@SuppressWarnings("unchecked")
323+
public void testUnflatten() {
324+
Map<String, Object> flatMap = map( "string", "value", "int", 10, "nested.anotherkey", "anotherValue", "nested.nested.somekey", "someValue", "nested.nested.somenumeric", 123 );
325+
TestUtil.testCall( db, "RETURN apoc.map.unflatten($map) AS value", map( "map", flatMap ), (r) -> {
326+
Map<String, Object> resultMap = (Map<String, Object>)r.get( "value" );
327+
assertEquals( map( "string", "value", "int", 10, "nested", map( "anotherkey", "anotherValue", "nested", map( "somekey", "someValue", "somenumeric", 123 ) ) ), resultMap );
328+
} );
329+
}
330+
331+
@Test (expected = QueryExecutionException.class)
332+
public void testUnflattenConflictingKeys() {
333+
Map<String, Object> flatMap = map( "key", "value", "key.nested", "anotherValue" );
334+
TestUtil.testCall( db, "RETURN apoc.map.unflatten($map) AS value", map( "map", flatMap ), (r) -> {} );
335+
}
336+
321337
@Test
322338
public void testSortedProperties() {
323339
TestUtil.testCall(db, "WITH {b:8, d:3, a:2, E: 12, C:9} as map RETURN apoc.map.sortedProperties(map, false) AS sortedProperties", (r) -> {

0 commit comments

Comments
 (0)