[英]How to flatten an array and get rid of null?
I am trying to take an arbitrarily deep-nested array and flatten the array, as well as get rid of any null objects in the array. 我试图获取一个任意深度嵌套的数组并展平该数组,并摆脱该数组中的任何空对象。
For example I want to be able to input a nested array like [1, 5, [[6, 4], 91, 12, null, [[null]]], -2]
and return a one-dimensional array without any null values. 例如,我希望能够输入一个嵌套数组,例如[1, 5, [[6, 4], 91, 12, null, [[null]]], -2]
然后返回一维数组而没有任何空值。 How would I go about solving this? 我将如何解决这个问题?
I provided my solution below, but I keep getting an 我在下面提供了解决方案,但我不断得到
I cannot be cast to java.lang.Integer error. 我无法转换为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;
}
A possible solution using the Stream API introduced in Java 8 is the following: 使用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();
}
The first point to consider is that an int[]
is not an Object[]
. 要考虑的第一点是int[]
不是Object[]
。 So, this method accepts a Object[]
to represent that it can be given any type of integer array with at least 2 dimensions, ie int[][]
, up to any number of dimensions. 因此,此方法接受一个Object[]
来表示可以为它提供至少2个维的任意类型的整数数组,即int[][]
,最多不限维数。 It filters out null elements, with the Objects::nonNull
predicate. 它使用Objects::nonNull
谓词过滤掉空元素。
Then the magic happens: the Stream<Object>
, returned by Arrays.stream(array)
, is flat mapped to an IntStream
: if the elements inside it are Object[]
, then it means that we still have more than 2 dimensions, and the method is recursively calling itself. 然后神奇的事情发生了:由Arrays.stream(array)
返回的Stream<Object>
被平面映射到IntStream
:如果其中的元素是Object[]
,则意味着我们仍然有两个以上的维度,并且该方法是递归调用自身。 On the other hand, if we have an instance of int[]
, then we can just replace it with a Stream of that. 另一方面,如果我们有int[]
的实例,那么我们可以用它的Stream代替它。
Example calling code: 调用代码示例:
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));
}
Of course, this method doesn't accept int[]
, which would be the case where is nothing to flatten (and nothing to filter since int
can't be null
). 当然,此方法不接受int[]
,在这种情况下,没有什么要扁平化(也没有要过滤的东西,因为int
不能为null
)。
One of simplest (but not necessary fastest) solution could be to: 一种最简单 (但不是必需最快)的解决方案是:
generate string which will represent your array ( Arrays.deepToString
can be helpful here) like 生成将代表您的数组的字符串( Arrays.deepToString
在这里可能会有所帮助),例如
"[null, [4, 5, 6], [3, 1, 10], [4, 2, 9], null, null]"
remove from it characters like [
]
,
从它的人物,如除去[
]
,
In short your solution could look like (I am assuming you are allowed to use Java 8) 简而言之,您的解决方案可能看起来像(我假设您被允许使用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());
}
In case you want to split floating point numbers and your locale is also using ,
as decimal mark 1,25
you would need to decide which ,
we should remove and which ,
is part of number and should stay. 如果您想分割浮点数并且您的语言环境也使用,
作为小数点1,25
,则需要确定哪个,
我们应该删除,哪个,
是数字的一部分,应该保留。 For such case solution could be removing ,
which has space after it (but we don't want to remove that space because we need it in split
). 对于这种情况,解决方案可以是remove ,
其后有空格(但是我们不想删除该空间,因为我们需要split
)。 Since replaceAll
is using regex we can use look-ahead (?=...)
mechanism which will allow us to test part after current match, but not include that tested part in match. 由于replaceAll
使用的是正则表达式,因此我们可以使用replaceAll
(?=...)
机制,该机制将允许我们在当前匹配之后测试零件,但不将该匹配的零件包括在匹配中。
So we would need to replaceAll("\\\\[|\\\\]|,(?=\\\\s)","")
which will ensure that removed ,
must have space after it, but will not remove that space. 因此,我们需要replaceAll("\\\\[|\\\\]|,(?=\\\\s)","")
这将确保删除,
之后它必须有空间,但不会删除空间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.