展平具有自我参考的列表列表。
我有列表列表,其中包含对自身的引用,我需要展平此列表。
EG。我有清单
A = [1,[2,[3]],A,]
扁平列表看起来像这样
A = [1,2,3]
这是我尝试过的(用Java):
public static void flattenRecurser(List<Integer> result, List<?> nested) {
for (Object item : nested) {
if (item instanceof List<?> && !freq.containsKey((List<?>) item)) {
flattenRecurser(result, (List<?>) item);
} else if (item instanceof Integer) {
result.add((Integer) item);
}
}
}
我在调用flattenRecurser
之前将嵌套添加到名为freq的map中static Map<List<?>, List<?>> freq = new HashMap<>();
freq.put(nested,nested);
List<Integer> result = new ArrayList<Integer>();
flattenRecurser(result, nested);
但是当我将嵌套列表放入freq映射时,我收到错误
查找嵌套对象的哈希码会导致错误。我将如何以不同的方式处理此问题,或者是否有找到嵌套对象的哈希的方法。
这是我得到的错误:
线程“main”中的异常java.lang.StackOverflowError at java.util.ArrayList.iterator(ArrayList.java:834)at java.util.AbstractList.hashCode(AbstractList.java:540)
我的代码中没有行号834或540
答案 0 :(得分:1)
您必须跟踪已添加到结果列表中的列表。你可以使用哈希集来做到这一点,但是List.hashCode
的实现似乎存在一个错误(?):虽然List.toString
可以处理包含自引用的列表,但List.hashCode
会遇到无限递归。相反,您可以使用System.identityHashCode
。
public static List flatten(List flatten, Set<Integer> ignore) {
List result = new LinkedList();
ignore.add(System.identityHashCode(flatten));
for (Object o : flatten) {
if (o instanceof List) {
if (! ignore.contains(System.identityHashCode(o))) {
result.addAll(flatten((List) o, ignore));
}
} else {
result.add(o);
}
}
return result;
}
示例:
List C = new ArrayList(Arrays.asList(4, 5, 6));
List B = new ArrayList(Arrays.asList(2, 3, C, 7));
List A = new ArrayList(Arrays.asList(1, B, 8, 9, C));
C.add(C);
B.add(B);
A.add(A);
System.out.println(A);
System.out.println(flatten(A, new HashSet<>()));
输出:
[1, [2, 3, [4, 5, 6, (this Collection)], 7, (this Collection)], 8, 9, [4, 5, 6, (this Collection)], (this Collection)]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
请注意,可以与此方法冲突,即具有相同身份哈希码的两个不同列表。在这种情况下,其中一个列表不会添加到结果中。或者,您可以循环整个ignore
集,并使用==
将每个元素与当前列表进行比较。
答案 1 :(得分:0)
你正在进行无休止的递归。如果item == nested - &gt;什么都不做。