Achatar matrizes aninhadas em java

Eu quero achatar matrizes aninhadas como:

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

manualmente em java eu ​​não consigo encontrar uma pista! : S

Eu tentei um guia de script java manual, mas ele não obtém uma solução

Eu criei uma class para resolver isso usando Java, o código também é mostrado abaixo.

Solução:

 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. * 

* @author conorgriffin */ public class IntegerArrayFlattener { /** * Flatten an array of arbitrarily nested arrays of integers into a flat array of integers. eg [[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 flatList = new ArrayList(); 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()]); } }

Testes Unitários:

 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}} ); } } 

A API Stream do Java 8 oferece uma solução compacta e flexível. Usando o método

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

você pode executar a operação como

 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)); 

ou quando você assume que os objects da folha são de um tipo específico:

 int[] flatInt = flatten(array).mapToInt(Integer.class::cast).toArray(); System.out.println("flat int: "+Arrays.toString(flat)); 

você pode tentar este código:

 String a = "[[[1],2],[3]],4] "; a= a.replaceAll("[(\\[|\\])]", ""); String[] b = a.split(","); 

Foi assim que resolvi esse problema em Java:

 public class ArrayUtil { /** * Utility to flatten an array of arbitrarily nested arrays of integers into * a flat array of integers. eg [[1,2,[3]],4] -> [1,2,3,4] * @param inputList */ public static Integer[] flattenArray(ArrayList inputList) { ArrayList flatten = new ArrayList(); 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 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) 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; } } 

Poderia ser aplainado pela abordagem iterativa.

 static class ArrayHolder implements Iterator { 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 flattened) { Deque 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); } } } 

Você pode encontrar a fonte completa aqui Você pode usar a recursion para resolver esse problema.

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

Aqui está o link para recursion .

É assim que eu resolvo. Não sabe que tipo de eficiência você está procurando. Mas sim. que faz o trabalho em JavaScript.

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

Uma maneira provavelmente mais eficiente de fazer isso seria usar o método reduce e concat de arr e recursion.

 function flattenDeep(arr1) { return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []); }