0

I'm building a small micro service to implement a couple of sorting algorithms using Java & Vert.x

One of my requirements is to handle nested lists like [5, [4, 3, 2], 1, [[0]]]

The request body is a JSON object like:

{"arr": [5, [4, 3, 2], 1, [[0]]]}

How can I parse a JSON object/ JSON array with a nested list to a flat list in Java?

// This is how I handle simple lists
private void doBubbleSort(RoutingContext routingContext) {

    JsonObject json = routingContext.getBodyAsJson();
    JsonArray jsonArray = json.getJsonArray("arr");

    // How do I get the size of the list if it is multi-dimensional
    int size = jsonArray.size();

    int[] unsortedList = new int[size];
    for (int i = 0; i < size; i++) {
        // Here I want to check whether the current item is an int or
        // another nested list. if it is a list, i want to loop over it
        // and also add it to the result
        unsortedList[i] = jsonArray.getInteger(i);
    }

    ...
}

The result I'm looking for:

int[5, 4, 3, 2, 1, 0]

I know I need to check whether the current value is of type int or list, but struggling to get it working with the type conversions from JSON to int to list.

In Python I can do this without the type conversions.

def flatten_list(arr: list):
    nested_arr = deepcopy(arr)

    while nested_arr:
        sublist = nested_arr.pop(0)

        if isinstance(sublist, int):
            yield sublist

        if isinstance(sublist, list):
            nested_arr = sublist + nested_arr
krankit
  • 62
  • 1
  • 8

1 Answers1

1

According to your answers try the following:

private void doBubbleSort(RoutingContext routingContext) {

    JsonObject json = routingContext.getBodyAsJson();
    JsonArray jsonArray = json.getJsonArray("arr");

    List<?> list = jsonArray.getList();

    List<Integer> flatList = list.stream()
        .map(this::getOrFlatten)
        .flatMap(List::stream)
        .collect(Collectors.toList());

    // convert List<Integer> to int[]
    // ...
}

private List<Integer> getOrFlatten(Object o) {
    if(o instanceof Integer) {
        return Collections.singletonList((Integer) o);
    } else if(o instanceof List) {
        List<?> list = (List) o;
        return list.stream()
            .map(this::getOrFlatten)
            .flatMap(List::stream)
            .collect(Collectors.toList());
    } else {
        throw new IllegalArgumentException(o.getClass() + " is not supported at getOrFlatten");
    }
}

Here you can find how to convert List to int []

aBnormaLz
  • 713
  • 4
  • 19
  • Thanks! Had no idea how to handle the 'unknown' values. The `List> list = jsonArray.getList();` was exactly what I needed. Will need to dig deeper into java generics – krankit Jan 02 '19 at 20:30
  • Your welcome :) also you can take a look at `list.parallelStream()`, if you want to run the multiple `getOrFlatten` calls concurrently. – aBnormaLz Jan 03 '19 at 09:46