Java 8-合并包含公共元素的所有子集
从一组“组”开始: 最终结果将是:Java 8-合并包含公共元素的所有子集,java,merge,java-8,set,Java,Merge,Java 8,Set,从一组“组”开始: 最终结果将是: Set 1 = {a, b, c, d, e, f, g, h, i, j} Set 2 = {k, l, m, n, o} Set 3 = {p, q, r} 任何关于如何实现这一点的建议都将不胜感激 编辑:如果集合不均匀,它将执行相同的操作。因此,如果它是一个方法,它将如下所示: public void doStuff(){ Set<Set<String>> groups = {{a,b,c}, {c,d,e,f}, {m,
Set 1 = {a, b, c, d, e, f, g, h, i, j}
Set 2 = {k, l, m, n, o}
Set 3 = {p, q, r}
任何关于如何实现这一点的建议都将不胜感激
编辑:如果集合不均匀,它将执行相同的操作。因此,如果它是一个方法,它将如下所示:
public void doStuff(){
Set<Set<String>> groups = {{a,b,c}, {c,d,e,f}, {m, n, o}}
Set<Set<String>> newGroups = mergeSubsets(groups);
System.out.println(newGroups);
}
public Set<Set<String>> mergeSubsets(Set<Set<String>> groups){
//some operations
}
import java.util.*;
公共类合并集{
公共静态void main(字符串…参数){
列表组=新的ArrayList();
字符串[]A={“A”,“b”,“c”};
字符串[]B={“c”,“d”,“e”,“f”};
字符串[]C={“f”、“g”、“h”、“i”、“j”};
字符串[]D={“k”,“l”,“m”};
字符串[]E={“m”,“n”,“o”};
字符串[]F={“p”,“q”,“r”};
add(新的HashSet(Arrays.asList(A));
add(新的HashSet(Arrays.asList(B));
add(新的HashSet(Arrays.asList(C));
add(新的HashSet(Arrays.asList(D));
add(新的HashSet(Arrays.asList(E));
add(新的HashSet(Arrays.asList(F));
Set newGroups=合并子集(组);
System.out.println(新组);
}
私有静态集合合并子集(列表组){
List newGroups=newarraylist();
Set init=groups.get(0);
组。移除(0);
newGroups.add(init);
而(!groups.isEmpty()){
从groupandupdatenewgroup(newGroups.get(newGroups.size()-1),groups)中删除mergedelement;
如果(!groups.isEmpty()){
init=groups.get(0);
组。移除(0);
newGroups.add(init);
}
}
返回新的HashSet(newGroups);
}
私有静态void removeMergedElementFromGroupAndUpdateNewGroup(设置master2,列表masterList){
迭代器迭代器=masterList.Iterator();
while(iterator.hasNext()){
Set strings=iterator.next();
布尔合并=strings.stream().anyMatch(string->master2.contains(string));
如果(合并){
master2.addAll(字符串);
iterator.remove();
}
}
}
}
希望这有助于取代集合组
我使用了列表组
以便于使用列表如果您有仅使用Set的限制,您可以通过将Set(比如yourSet)传递到List实现的构造函数中,从Set生成List,例如
groups = new ArrayList<>(yourSet);
groups=newarraylist(yourSet);
您可以按照您在问题陈述中描述的方式实现算法——找到相交集并合并它们,直到没有任何东西可合并为止。标准库有一种方法可以帮助确定两个集合是否有任何共同元素:
// this implementation sacrifices efficiency for clarity
public Set<Set<String>> mergeSubsets(Set<Set<String>> groups) {
Set<Set<String>> result = new HashSet<>();
for (Set<String> set : groups) {
// try to find a set in result that intersects this set
// if one is found, merge the two. otherwise, add this set to result
result.stream()
.filter(x -> !Collections.disjoint(x, set))
.findAny()
.ifPresentOrElse( // this method was added in java 9
x -> x.addAll(set),
() -> result.add(new HashSet<>(set))
);
}
// if nothing got merged we are done; otherwise, recurse and try again
return result.size() == groups.size() ? result : mergeSubsets(result);
}
//为了清晰起见,此实现牺牲了效率
公共集合合并子集(集合组){
Set result=new HashSet();
用于(集合:组){
//尝试在结果中找到与此集合相交的集合
//如果找到一个,则合并两个。否则,将此集合添加到结果
result.stream()
.filter(x->!集合.不相交(x,集合))
.findAny()
.ifPresentOrElse(//此方法是在java 9中添加的
x->x.addAll(设置),
()->result.add(新哈希集(set))
);
}
//如果没有合并任何内容,我们就完成了;否则,递归并重试
返回result.size()==groups.size()?结果:合并子集(结果);
}
以下是基于@NiksVij解决方案的命令式方法。显然,@NiksVij的解决方案是不正确的,这个答案旨在解决这个问题并进一步扩展:
public class MergeSet {
public static void main(String... args) {
List<Set<String>> list = new ArrayList<>();
String[] A = {"a", "c", "e", "g"};
String[] B = {"b", "d", "f", "h"};
String[] C = {"c", "e", "f"};
String[] D = {"b"};
list.add(new HashSet<>(Arrays.asList(A)));
list.add(new HashSet<>(Arrays.asList(C)));
list.add(new HashSet<>(Arrays.asList(B)));
list.add(new HashSet<>(Arrays.asList(D)));
List<Set<String>> newGroups = merge(list);
System.out.println(newGroups);
}
@SuppressWarnings("empty-statement")
private static <T> List<Set<T>> merge(List<Set<T>> list) {
if (list == null || list.isEmpty()) {
return list;
}
List<Set<T>> merged = new ArrayList<>();
do {
merged.add(list.get(0));
list.remove(0);
while (mergeStep(merged.get(merged.size() - 1), list));
} while (!list.isEmpty());
return merged;
}
private static <T> boolean mergeStep(Set<T> setToCheck, List<Set<T>> remainingList) {
boolean atLeastOnceMerged = false;
Iterator<Set<T>> iterator = remainingList.iterator();
while (iterator.hasNext()) {
Set<T> elements = iterator.next();
boolean doMerge = !Collections.disjoint(elements, setToCheck);
if (doMerge) {
atLeastOnceMerged |= doMerge;
setToCheck.addAll(elements);
iterator.remove();
}
}
return atLeastOnceMerged;
}
公共类合并集{
公共静态void main(字符串…参数){
列表=新的ArrayList();
字符串[]A={“A”、“c”、“e”、“g”};
字符串[]B={“B”,“d”,“f”,“h”};
字符串[]C={“C”,“e”,“f”};
字符串[]D={“b”};
add(新的HashSet(Arrays.asList(A));
add(新的HashSet(Arrays.asList(C));
add(新的HashSet(Arrays.asList(B));
add(新的HashSet(Arrays.asList(D));
列表新建组=合并(列表);
System.out.println(新组);
}
@SuppressWarnings(“空语句”)
私有静态列表合并(列表){
if(list==null | | list.isEmpty()){
退货清单;
}
列表合并=新建ArrayList();
做{
merged.add(list.get(0));
列表。删除(0);
while(mergeStep(merged.get(merged.size()-1),list));
}而(!list.isEmpty());
返回合并;
}
私有静态布尔合并步骤(设置setToCheck,列表remainingList){
布尔值AtleastOnce=false;
迭代器迭代器=remainingList.Iterator();
while(iterator.hasNext()){
Set elements=iterator.next();
布尔值doMerge=!Collections.disjoint(elements,setToCheck);
如果(多梅尔奇){
至少|=多梅尔奇;
setToCheck.addAll(元素);
iterator.remove();
}
}
至少返回一次;
}
你试图达到相同的目的是什么?集合1、2、3的分组逻辑是什么?任何由非空交集组成的任意两个子集都应该合并。我相信它适合某种递归解决方案,但我很难弄清楚这一点。在纸上解决它-显然背后有一个算法然后写Java代码你的结果集怎么会有两个c
s?好吧,我做得更好,{{a,b,c},{c,d,e,f},{e,n,o},这个结果会是什么?这对String[]a={a”,“c”,“e”,“e”,“g};String[]b={b”,“d”,“f”,“h};String[]c={c”,“c”,“e”,“f};String[]D={“b”};
逻辑正常。它缺少一个空检查。我们添加了该检查。感谢您指出缺少的内容
import java.util.*;
public class MergeSet {
public static void main(String... args) {
List<Set<String>> groups = new ArrayList<>();
String[] A = {"a", "b", "c"};
String[] B = {"c", "d", "e", "f"};
String[] C = {"f", "g", "h", "i", "j"};
String[] D = {"k", "l", "m"};
String[] E = {"m", "n", "o"};
String[] F = {"p", "q", "r"};
groups.add(new HashSet<>(Arrays.asList(A)));
groups.add(new HashSet<>(Arrays.asList(B)));
groups.add(new HashSet<>(Arrays.asList(C)));
groups.add(new HashSet<>(Arrays.asList(D)));
groups.add(new HashSet<>(Arrays.asList(E)));
groups.add(new HashSet<>(Arrays.asList(F)));
Set<Set<String>> newGroups = mergeSubsets(groups);
System.out.println(newGroups);
}
private static Set<Set<String>> mergeSubsets(List<Set<String>> groups) {
List<Set<String>> newGroups = new ArrayList<>();
Set<String> init = groups.get(0);
groups.remove(0);
newGroups.add(init);
while (!groups.isEmpty()) {
removeMergedElementFromGroupAndUpdateNewGroup(newGroups.get(newGroups.size() - 1), groups);
if(!groups.isEmpty()) {
init = groups.get(0);
groups.remove(0);
newGroups.add(init);
}
}
return new HashSet<>(newGroups);
}
private static void removeMergedElementFromGroupAndUpdateNewGroup(Set<String> master2, List<Set<String>> masterList) {
Iterator<Set<String>> iterator = masterList.iterator();
while (iterator.hasNext()) {
Set<String> strings = iterator.next();
boolean merge = strings.stream().anyMatch(string -> master2.contains(string));
if (merge) {
master2.addAll(strings);
iterator.remove();
}
}
}
}
groups = new ArrayList<>(yourSet);
// this implementation sacrifices efficiency for clarity
public Set<Set<String>> mergeSubsets(Set<Set<String>> groups) {
Set<Set<String>> result = new HashSet<>();
for (Set<String> set : groups) {
// try to find a set in result that intersects this set
// if one is found, merge the two. otherwise, add this set to result
result.stream()
.filter(x -> !Collections.disjoint(x, set))
.findAny()
.ifPresentOrElse( // this method was added in java 9
x -> x.addAll(set),
() -> result.add(new HashSet<>(set))
);
}
// if nothing got merged we are done; otherwise, recurse and try again
return result.size() == groups.size() ? result : mergeSubsets(result);
}
public class MergeSet {
public static void main(String... args) {
List<Set<String>> list = new ArrayList<>();
String[] A = {"a", "c", "e", "g"};
String[] B = {"b", "d", "f", "h"};
String[] C = {"c", "e", "f"};
String[] D = {"b"};
list.add(new HashSet<>(Arrays.asList(A)));
list.add(new HashSet<>(Arrays.asList(C)));
list.add(new HashSet<>(Arrays.asList(B)));
list.add(new HashSet<>(Arrays.asList(D)));
List<Set<String>> newGroups = merge(list);
System.out.println(newGroups);
}
@SuppressWarnings("empty-statement")
private static <T> List<Set<T>> merge(List<Set<T>> list) {
if (list == null || list.isEmpty()) {
return list;
}
List<Set<T>> merged = new ArrayList<>();
do {
merged.add(list.get(0));
list.remove(0);
while (mergeStep(merged.get(merged.size() - 1), list));
} while (!list.isEmpty());
return merged;
}
private static <T> boolean mergeStep(Set<T> setToCheck, List<Set<T>> remainingList) {
boolean atLeastOnceMerged = false;
Iterator<Set<T>> iterator = remainingList.iterator();
while (iterator.hasNext()) {
Set<T> elements = iterator.next();
boolean doMerge = !Collections.disjoint(elements, setToCheck);
if (doMerge) {
atLeastOnceMerged |= doMerge;
setToCheck.addAll(elements);
iterator.remove();
}
}
return atLeastOnceMerged;
}