我试图采用任意深度嵌套的数组并展平数组,以及摆脱数组中的任何空对象。
例如,我希望能够输入一个嵌套数组
[1, 5, [[6, 4], 91, 12, null, [[null]]], -2]
并返回一个没有任何空值的一维数组。我该如何解决这个问题?
我在下面提供了我的解决方案,但我一直在
我无法转换为java.lang.Integer错误。
public static void main(String[] args) {
int[][] numbers = {null, {4, 5, 6},{3, 1, 10}, {4, 2, 9}, null, null};
flatten(numbers);
}
public static ArrayList<Integer> flatten(Object[] nestedNumbers) {
if (nestedNumbers == null) return null;
ArrayList<Integer> flattenedNumbers = new ArrayList<>();
for (Object element : nestedNumbers) {
if (element != null) {
flattenedNumbers.add((Integer)element);
}
}
return flattenedNumbers;
}
答案 0 :(得分:6)
使用Java 8中引入的Stream API的可能解决方案如下:
public static int[] flatten(Object[] array) {
return Arrays.stream(array)
.filter(Objects::nonNull)
.flatMapToInt(a -> {
if (a instanceof Object[]) return Arrays.stream(flatten((Object[]) a));
return Arrays.stream((int[]) a);
})
.toArray();
}
要考虑的第一点是int[]
不是Object[]
。因此,此方法接受Object[]
来表示它可以被赋予任何类型的至少具有2维的整数数组,即int[][]
,直到任意数量的维度。它使用Objects::nonNull
谓词过滤掉空元素。
然后神奇的事情发生了:由Stream<Object>
返回的Arrays.stream(array)
平面映射到IntStream
:如果其中的元素是Object[]
,则意味着我们仍然有超过2个维度,并且该方法是递归调用自身的。另一方面,如果我们有一个int[]
的实例,那么我们可以用它的Stream替换它。
调用代码示例:
public static void main(String[] args) {
int[][][] numbers = {null, {{4}, {5}, {6,1}},{{3,2}, {1}, {10}}, {{4,1}, {2,3}, {9,8}}, null, null};
int[] flat = flatten(numbers);
System.out.println(Arrays.toString(flat));
}
当然,此方法不接受int[]
,这可能是没有什么可以展平的情况(并且由于int
不能null
而无需过滤。)
答案 1 :(得分:2)
最简单的(但不是最快的必要)解决方案之一可能是:
生成代表你的数组的字符串(Arrays.deepToString
在这里很有用),比如
"[null, [4, 5, 6], [3, 1, 10], [4, 2, 9], null, null]"
从中移除[
]
,
简而言之,您的解决方案可能看起来像(我假设您可以使用Java 8)
public static List<Integer> flatten(Object[] nestedNumbers) {
String text = Arrays.deepToString(nestedNumbers);
System.out.println(text);
return Stream.of(text.replaceAll("\\[|\\]|,", "").split("\\s+"))
.filter(s->!s.equals("null"))
.map(Integer::parseInt)
.collect(Collectors.toList());
}
如果你想分割浮点数并且你的语言环境也使用,
作为十进制标记1,25
,你需要决定我们应该删除哪个,
以及{{1}是数字的一部分,应该留下来。对于这种情况,解决方案可能是删除,
之后的空格(但我们不想删除该空格,因为我们需要,
)。由于split
正在使用正则表达式,我们可以使用先行replaceAll
机制,这将允许我们在当前匹配后测试部分,但不包括匹配中的测试部分。
因此我们需要(?=...)
,这将确保已移除的replaceAll("\\[|\\]|,(?=\\s)","")
后面必须有空格,但不会删除该空格。