Flatten nested arrays in java

前端 未结 6 647
失恋的感觉
失恋的感觉 2020-12-01 13:32

I want to flatten nested arrays like:

[[[1],2],[3]],4] -> [1,2,3,4] 

manually in java I can\'t find a clue ! :S

I have tried a

相关标签:
6条回答
  • 2020-12-01 13:58

    This is how I solved this problem in Java:

    public class ArrayUtil {
    
        /**
         * Utility to flatten an array of arbitrarily nested arrays of integers into
         * a flat array of integers. e.g. [[1,2,[3]],4] -> [1,2,3,4]
         * @param inputList
         */
        public static Integer[] flattenArray(ArrayList<Object> inputList) {
    
            ArrayList<Integer> flatten = new ArrayList<Integer>();
            if (inputList.size() <= 0) {
                return new Integer[0];                          // if the inputList is empty, return an empty Integer[] array.
            }
    
            for (Object obj : inputList) {
                recursiveFlatten(flatten, obj);                 // otherwise we can recursively flatten the input list.
            }
    
            Integer [] flatArray = new Integer[flatten.size()];
            return flatArray = flatten.toArray(flatArray);      
        }
    
        /**
         * Recursively flatten a nested array.
         * @param flatten
         * @param o
         */
        private static void recursiveFlatten(ArrayList<Integer> flatten, Object o){
            if(isInteger(o)){                               // if the object is of type Integer, just add it into the list.
                flatten.add((Integer)o);
            } else if(o instanceof ArrayList){              // otherwise, we need to call to recursively flatten the array
                for(Object obj : (ArrayList<Object>) o){    // for the case where there are deeply nested arrays.
                    recursiveFlatten(flatten, obj);
                }
            }
        }
    
        /**
         * Return true if object belongs to Integer class,
         * else return false.
         * @param obj
         * @return
         */
        private static boolean isInteger(Object obj) {
            return obj instanceof Integer;
        }
    
    }
    
    0 讨论(0)
  • 2020-12-01 14:08

    That's the way I would solve it. Don't know which kind of efficiency you are looking for. But yeah. that does the job in JavaScript.

    arr.toString().split(',').filter((item) => item).map((item) => Number(item))

    A probably more efficient way to do this would be to use reduce and concat method from arr and recursion.

    function flattenDeep(arr1) {
       return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
    }
    
    0 讨论(0)
  • 2020-12-01 14:15

    Java 8’s Stream API offers a compact and flexible solution. Using the method

    private static Stream<Object> flatten(Object[] array) {
        return Arrays.stream(array)
                     .flatMap(o -> o instanceof Object[]? flatten((Object[])o): Stream.of(o));
    }
    

    you can perform the operation as

    Object[] array = { 1, 2, new Object[]{ 3, 4, new Object[]{ 5 }, 6, 7 }, 8, 9, 10 };
    System.out.println("original: "+Arrays.deepToString(array));
    
    Object[] flat = flatten(array).toArray();
    System.out.println("flat:     "+Arrays.toString(flat));
    

    or when you assume the leaf objects to be of a specific type:

    int[] flatInt = flatten(array).mapToInt(Integer.class::cast).toArray();
    System.out.println("flat int: "+Arrays.toString(flat));
    
    0 讨论(0)
  • 2020-12-01 14:18

    I created a class to solve this using Java, the code is also shown below.

    Solution:

    package com.conorgriffin.flattener;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * Flattens an array of arbitrarily nested arrays of integers into a flat array of integers.
     * <p/>
     * @author conorgriffin
     */
    public class IntegerArrayFlattener {
    
        /**
         * Flatten an array of arbitrarily nested arrays of integers into a flat array of integers. e.g. [[1,2,[3]],4] -> [1,2,3,4].
         *
         * @param inputArray an array of Integers or nested arrays of Integers
         * @return flattened array of Integers or null if input is null
         * @throws IllegalArgumentException
         */
        public static Integer[] flatten(Object[] inputArray) throws IllegalArgumentException {
    
            if (inputArray == null) return null;
    
            List<Integer> flatList = new ArrayList<Integer>();
    
            for (Object element : inputArray) {
                if (element instanceof Integer) {
                    flatList.add((Integer) element);
                } else if (element instanceof Object[]) {
                    flatList.addAll(Arrays.asList(flatten((Object[]) element)));
                } else {
                    throw new IllegalArgumentException("Input must be an array of Integers or nested arrays of Integers");
                }
            }
            return flatList.toArray(new Integer[flatList.size()]);
        }
    }
    

    Unit Tests:

    package com.conorgriffin.flattener;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    /**
     * Tests IntegerArrayFlattener
     */
    public class IntegerArrayFlattenerTest {
    
        Integer[] expectedArray = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
        @Test
        public void testNullReturnsNull() throws IllegalArgumentException {
            Assert.assertNull(
                    "Testing a null argument",
                    IntegerArrayFlattener.flatten(null)
            );
        }
    
        @Test
        public void testEmptyArray() throws IllegalArgumentException {
            Assert.assertArrayEquals(
                    "Testing an empty array",
                    new Integer[]{},
                    IntegerArrayFlattener.flatten(new Object[]{})
            );
        }
    
        @Test
        public void testFlatArray() throws IllegalArgumentException {
            Assert.assertArrayEquals(
                    "Testing a flat array",
                    expectedArray,
                    IntegerArrayFlattener.flatten(new Object[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
            );
        }
    
        @Test
        public void testNestedArray() throws IllegalArgumentException {
            Assert.assertArrayEquals(
                    "Testing nested array",
                    expectedArray,
                    IntegerArrayFlattener.flatten(new Object[]{1, 2, 3, 4, new Object[]{5, 6, 7, 8}, 9, 10})
            );
        }
    
        @Test
        public void testMultipleNestedArrays() throws IllegalArgumentException {
            Assert.assertArrayEquals(
                    "Testing multiple nested arrays",
                    expectedArray,
                    IntegerArrayFlattener.flatten(new Object[]{1, 2, new Object[]{3, 4, new Object[]{5}, 6, 7}, 8, 9, 10})
            );
        }
    
        @Test(expected = IllegalArgumentException.class)
        public void throwsExceptionForObjectInArray() throws IllegalArgumentException {
            IntegerArrayFlattener.flatten(
                    new Object[]{new Object()}
            );
        }
    
        @Test(expected = IllegalArgumentException.class)
        public void throwsExceptionForObjectInNestedArray() throws IllegalArgumentException {
            IntegerArrayFlattener.flatten(
                    new Object[]{1, 2, new Object[]{3, new Object()}}
            );
        }
    
        @Test(expected = IllegalArgumentException.class)
        public void throwsExceptionForNullInArray() throws IllegalArgumentException {
            IntegerArrayFlattener.flatten(
                    new Object[]{null}
            );
        }
    
        @Test(expected = IllegalArgumentException.class)
        public void throwsExceptionForNullInNestedArray() throws IllegalArgumentException {
            IntegerArrayFlattener.flatten(
                    new Object[]{1, 2, new Object[]{3, null}}
            );
        }
    
    }
    
    0 讨论(0)
  • 2020-12-01 14:19

    you can try this code:

    String a = "[[[1],2],[3]],4] ";
    a= a.replaceAll("[(\\[|\\])]", "");
    String[] b = a.split(",");
    
    0 讨论(0)
  • 2020-12-01 14:20

    It could be flattened by iterative approach.

    static class ArrayHolder implements Iterator<Object> {
        private final Object[] elements;
        private int index = -1;
    
        public ArrayHolder(final Object[] elements) {
            this.elements = elements;
        }
    
        @Override
        public boolean hasNext() {
            return Objects.nonNull(elements) && ++index < elements.length;
        }
    
        @Override
        public Object next() {
            if (Objects.isNull(elements) || (index == -1 || index > elements.length))
                throw new NoSuchElementException();
    
            return elements[index];
        }
    }
    
    
    private static boolean hasNext(ArrayHolder current) {
        return Objects.nonNull(current) && current.hasNext();
    }
    
    private void flat(Object[] elements, List<Object> flattened) {
        Deque<ArrayHolder> stack = new LinkedList<>();
        stack.push(new ArrayHolder(elements));
    
        ArrayHolder current = null;
        while (hasNext(current)
                || (!stack.isEmpty() && hasNext(current = stack.pop()))) {
            Object element = current.next();
    
            if (Objects.nonNull(element) && element.getClass().isArray()) {
                Object[] e = (Object[]) element;
                stack.push(current);
                stack.push(new ArrayHolder(e));
                current = null;
            } else {
                flattened.add(element);
            }
        }
    }
    

    You can find the full source here You can use recursion to solve this problem.

    private void flat(Object[] elements, List<Object> flattened) {
        for (Object element : elements)
        {
            if (Objects.nonNull(element) && element.getClass().isArray())
            {
                flat((Object[])element, flattened);
            }
            else
            {
                flattened.add(element);
            }
        }
    }
    

    Here is the link for recursion.

    0 讨论(0)
提交回复
热议问题