4

I'm struggling to create the right logic to flatten an array. I essentially want to duplicate parent rows for each child item in a nested array. The number of nested arrays could vary. I've been creating Java lists bc I find them easy to work with, but open to any solution. The nature of this problem is I'm starting with some nested JSON that I want to convert into a flat csv to load into a database table. Thanks for the help.

Example:

[1,2,[A,B,[Cat,Dog]],3]

I've created the above as a List. Each item is either a string or another List.

Result:

[1,2,A,Cat,3],
[1,2,A,Dog,3],
[1,2,B,Cat,3],
[1,2,B,Dog,3]

Here's what I have so far. Obviously not working.

private static List<List<String>> processData(List<String> row, List<Object> data, List<List<String>> rowList) {
    List<List<String>> tempRowList = new ArrayList<List<String>>();
    for (Object i : data) {
        if (i instanceof List<?>) {
            flattenArray((List<Object>) i, row, rowList);
        } else {
            for (List<String> r : rowList) {
                r.add(i.toString()); //add item to all rows
            }
        }
    }
    return rowList;

private static void flattenArray(List<Object> arrayObject, List<String> rowToCopy, List<List<String>> rowList) {

    for (Object x : arrayObject) {

        if (x instanceof List<?>) {
            for (List<String> t : rowList) {
                flattenArray((List<Object>) x, t, rowList);
            }

        } else {
            List<String> newRow = new ArrayList<String>(rowToCopy); //copy row

            List<Object> t = new ArrayList<Object>();
            t.add(x);

            List<List<String>> innerRowList = new ArrayList<List<String>>();
            innerRowList.add(newRow);

            processData(newRow, t, innerRowList); //pass in new copied row. object to add, 
            rowList.add(newRow);

        }

    }
    rowList.remove(rowToCopy);
}

And i set everything up like this.

public static void main(String[] args) {

    List<Object> data = new ArrayList<Object>();
    List<List<String>> rowList = new ArrayList<List<String>>();

    data.add("1");
    data.add("2");

    List<Object> l1 = new ArrayList<Object>();
    l1.add("A");
    l1.add("B");        
    List<Object> l2 = new ArrayList<Object>();
    l2.add("dog");
    l2.add("cat");
    l1.add(l2);
    data.add(l1);

    data.add("3");

    List<String> r0 = new ArrayList<String>();
    rowList.add(r0);
    System.out.println(data);
    rowList = processData(r0, data, rowList);
    System.out.println(rowList);
}
5
  • 1
    What code have you written? Lets see it? Commented Oct 24, 2016 at 12:52
  • 1
    ok, added my code. I feel like I've way over complicated this. Commented Oct 24, 2016 at 13:02
  • That's fine, now we can help go through what problems you have Commented Oct 24, 2016 at 13:08
  • 1
    [1,2,[A,B,[Cat,Dog]],3] - will [1,2,[A,B],[Cat,Dog],3] result in exactly same output? Looks quite arbitrary that it behaves same way. Commented Oct 24, 2016 at 14:11
  • yes, both of those should yield the same output. Essentially 4 arrays. Commented Oct 24, 2016 at 14:55

1 Answer 1

2

I think this should work for you if you're using Java 8:

    List<Object> a = new ArrayList<>();
    List<Object> a1 = new ArrayList<>();
    a1.add("v");
    a1.add("w");
    List<Object> a2 = new ArrayList<>();
    a2.add("ww");
    a.add("a");
    a.add("b");
    a.add("c");
    a.add("d");
    a.add(a1);
    a.add(a2);
    List<Object> b = new ArrayList<>();

    a.stream().flatMap(x -> x instanceof String ? Stream.of(x) : ((List) x).stream()).forEach(b::add);

    System.out.println(a);
    System.out.println(b);

b list will contain flattened a list. Output is:

[a, b, c, d, [v, w], [ww]]
[a, b, c, d, v, w, ww]
Sign up to request clarification or add additional context in comments.

4 Comments

I am using Java 8. I've only played around with streams a little bit. Was curious if they could help me here.
I'm not sure how to use them though based on your example.
Andrew this should work. I know it's ugly, I'll try to prettify it ASAP.
that seems to flatten it all into one level. I want an array for each item in the top level. See example and result at the top.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.