有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何在Java中找到多个集合的所有交集的列表?

我有一份布景清单:

setlist = [s1,s2,s3...sn]

我想要一个集合的全方位比较,即2^n个集合:

setIntersection = [s1 ∩ s2, s1 ∩ s2 ∩ s3, ....., s2 ∩ s3 ∩ s4, ...., sn-1 ∩ sn]

在Java中实现这一点的最佳方法是什么

例如,如果我只使用了5套。我希望能够填充5 circle venn diagram.的所有重叠

我正试图通过一系列场景来实现这一点:

List<Set<People>> lListSets = new ArrayList<Set<People>>();
for (DaysObject day : listOfDaysInJanuary) {
        lListSets.add(day.peopleOneInternet());
}
findPowerSetsAndCompare(lListSets, listOfDaysInJanuary);

我想找到一些结果,比如:

January 1 (Bob, Sally, Tommy)
January 1, January 2 (Sally, Tommy)
...
so on for all possible combination of days.

本质上,我要问的是如何将powerset algorithm与集合并集相结合


共 (1) 个答案

  1. # 1 楼答案

    What would be the best way to do this in Java?

    你描述的第一部分是powerset(上周我编辑了你的问题)。然后,您将获得动力集中每套装置的交点

    因为你要做的是一个集合的幂集,而不是一个简单的整数幂集,所以实现将更加复杂

    额外学分

    我为你的需求写了一个基本的实现,作为你如何实现它的一个例子。本例中的所有方法和类型都是Example类的成员

    示例类,仅使用其main方法演示工作代码。我相信您会原谅我在演示中使用了不推荐的Date构造函数

    import java.text.*;
    import java.util.*;
    
    public class Example
    {
        public static void main(String[] args) {
            // create simple test harness
            Set<PeopleByDays> peepsByDay = new HashSet<PeopleByDays>();
            peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 1),
                Person.BOB, Person.FRANK, Person.JIM, Person.JUDY, Person.SALLY));
            peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 2),
                Person.BOB, Person.FRANK, Person.JIM, Person.JUDY, Person.TOMMY));
            peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 3),
                Person.BOB, Person.FRANK, Person.JIM, Person.SALLY, Person.TOMMY));
            peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 4),
                Person.BOB, Person.FRANK, Person.JUDY, Person.SALLY, Person.TOMMY));
            peepsByDay.add(new PeopleByDays(new Date(2015 - 1900, Calendar.JANUARY, 5),
                Person.BOB, Person.JIM, Person.JUDY, Person.SALLY, Person.TOMMY));
    
            // make powerSet, then intersect, then sort
            Set<Set<PeopleByDays>> powerPeeps = powerSet(peepsByDay);
            List<PeopleByDays> powerPeepsIntersected = intersect(powerPeeps);
            sort(powerPeepsIntersected);
    
            // print out results
            for (PeopleByDays peeps: powerPeepsIntersected) {
                String daysFormatted = format(peeps.getDays());
                System.out.print(daysFormatted);
                System.out.println(peeps);
            }
        }
    
        // all other Example members as defined in this answer
    }
    

    Person是一种简单的enum人名类型。在这里使用枚举的好处是,它可以为所需的HashSet行为提供适当的equals()hashCode()实现

        static enum Person {
            BOB, FRANK, JIM, JUDY, SALLY, TOMMY;
        }
    

    PeopleByDays扩展HashSet<Person>以收集另外一组Date对象来表示日期。覆盖retainAll()(intersect)以合并天数;覆盖equals()hashSet()以在外部集合中实现正确的行为

        static class PeopleByDays extends HashSet<Person> {
            private final Set<Date> days = new HashSet<Date>();
    
            public PeopleByDays() {
                super();
            }
            public PeopleByDays(Date day, Person... people) {
                super(Arrays.asList(people));
                this.days.add(day);
            }
            public PeopleByDays(PeopleByDays other) {
                super(other);
                this.days.addAll(other.days);
            }
    
            public List<Date> getDays() {
                return new ArrayList<Date>(this.days);
            }
    
            @Override
            public boolean retainAll(Collection<?> c) {
                if (c instanceof PeopleByDays) {
                    this.days.addAll(((PeopleByDays)c).days);
                }
                return super.retainAll(c);
            }
    
            @Override
            public boolean equals(Object o) {
                return super.equals(o) && this.days.equals(((PeopleByDays) o).days);
            }
            @Override
            public int hashCode() {
                return super.hashCode() + this.days.hashCode();
            }
        }
    

    powerSet()方法,逐字取自this answer

        public static <T> Set<Set<T>> powerSet(Set<T> originalSet) {
            Set<Set<T>> sets = new HashSet<Set<T>>();
            if (originalSet.isEmpty()) {
                sets.add(new HashSet<T>());
                return sets;
            }
            List<T> list = new ArrayList<T>(originalSet);
            T head = list.get(0);
            Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
            for (Set<T> set: powerSet(rest)) {
                Set<T> newSet = new HashSet<T>();
                newSet.add(head);
                newSet.addAll(set);
                sets.add(newSet);
                sets.add(set);
            }
            return sets;
        }
    

    intersect()方法为动力集中的每组集合创建交集

        static List<PeopleByDays> intersect(Set<Set<PeopleByDays>> powerSet) {
            List<PeopleByDays> intersected = new ArrayList<PeopleByDays>();
            for (Set<PeopleByDays> powerElement: powerSet) {
                PeopleByDays intersection = null;
                if (powerElement.isEmpty()) {
                    intersection = new PeopleByDays();
                } else for (PeopleByDays peeps: powerElement) {
                    if (intersection == null) {
                        intersection = new PeopleByDays(peeps);
                    } else {
                        intersection.retainAll(peeps);
                    }
                }
                intersected.add(intersection);
            }
            return intersected;
        }
    

    sort()方法按日期对生成的相交集进行排序

        static void sort(List<PeopleByDays> peeps) {
            Collections.sort(peeps, new Comparator<PeopleByDays>() {
                @Override
                public int compare(PeopleByDays p1, PeopleByDays p2) {
                    List<Date> days1 = p1.getDays();
                    List<Date> days2 = p2.getDays();
                    Collections.sort(days1);
                    Collections.sort(days2);
                    for (int i = 0; i < days1.size() && i < days2.size(); i++) {
                        int compare = days1.get(i).compareTo(days2.get(i));
                        if (compare != 0) {
                            return compare;
                        }
                    }
                    return days1.size() - days2.size();
                }
            });
        }
    

    format()方法格式化每个交叉口的天数列表

        static String format(List<Date> days) {
            if (days.isEmpty()) {
                return "";
            }
            StringBuilder sb = new StringBuilder();
            DateFormat format = new SimpleDateFormat("MMM d");
            Collections.sort(days);
            String separator = "";
            for (Date day: days) {
                sb.append(separator);
                sb.append(format.format(day));
                separator = ", ";
            }
            sb.append(" ");
            return sb.toString();
        }
    

    最后是输出

    []
    Jan 1 [BOB, JUDY, FRANK, JIM, SALLY]
    Jan 1, Jan 2 [BOB, JUDY, FRANK, JIM]
    Jan 1, Jan 2, Jan 3 [BOB, FRANK, JIM]
    Jan 1, Jan 2, Jan 3, Jan 4 [BOB, FRANK]
    Jan 1, Jan 2, Jan 3, Jan 4, Jan 5 [BOB]
    Jan 1, Jan 2, Jan 3, Jan 5 [BOB, JIM]
    Jan 1, Jan 2, Jan 4 [BOB, JUDY, FRANK]
    Jan 1, Jan 2, Jan 4, Jan 5 [BOB, JUDY]
    Jan 1, Jan 2, Jan 5 [BOB, JUDY, JIM]
    Jan 1, Jan 3 [BOB, FRANK, JIM, SALLY]
    Jan 1, Jan 3, Jan 4 [BOB, FRANK, SALLY]
    Jan 1, Jan 3, Jan 4, Jan 5 [BOB, SALLY]
    Jan 1, Jan 3, Jan 5 [BOB, JIM, SALLY]
    Jan 1, Jan 4 [BOB, JUDY, FRANK, SALLY]
    Jan 1, Jan 4, Jan 5 [BOB, JUDY, SALLY]
    Jan 1, Jan 5 [BOB, JUDY, JIM, SALLY]
    Jan 2 [BOB, JUDY, TOMMY, FRANK, JIM]
    Jan 2, Jan 3 [BOB, TOMMY, FRANK, JIM]
    Jan 2, Jan 3, Jan 4 [BOB, TOMMY, FRANK]
    Jan 2, Jan 3, Jan 4, Jan 5 [BOB, TOMMY]
    Jan 2, Jan 3, Jan 5 [BOB, TOMMY, JIM]
    Jan 2, Jan 4 [BOB, JUDY, TOMMY, FRANK]
    Jan 2, Jan 4, Jan 5 [BOB, JUDY, TOMMY]
    Jan 2, Jan 5 [BOB, JUDY, TOMMY, JIM]
    Jan 3 [BOB, TOMMY, FRANK, JIM, SALLY]
    Jan 3, Jan 4 [BOB, TOMMY, FRANK, SALLY]
    Jan 3, Jan 4, Jan 5 [BOB, TOMMY, SALLY]
    Jan 3, Jan 5 [BOB, TOMMY, JIM, SALLY]
    Jan 4 [BOB, JUDY, TOMMY, FRANK, SALLY]
    Jan 4, Jan 5 [BOB, JUDY, TOMMY, SALLY]
    Jan 5 [BOB, JUDY, TOMMY, JIM, SALLY]
    

    希望有帮助。我修补它的时间比我预想的要长得多;)但仍然没有对输出中的人名进行排序