【问题标题】:Is there a way to find common elements in multiple lists?有没有办法在多个列表中找到共同元素?
【发布时间】:2013-02-17 12:05:16
【问题描述】:

我有一个整数数组列表。我需要找到它们之间的共同点。我能想到的是Common elements in two lists中所列内容的扩展

Example would be 
[1,3,5],
[1,6,7,9,3],
[1,3,10,11]

should result in [1,3]

数组中也没有重复项。

有没有直接的方法来做到这一点?

【问题讨论】:

  • 您是否要与 int 数组列表的值相交?您所说的“直截了​​当”是什么意思?
  • “常见”表示它们出现在每个列表中,还是出现在多个列表中?
  • 我的意思是“直截了当”是某种库中的一种方法,例如 apache commons、colt、guava 等。
  • 您可以遍历每个数组中的所有元素并填充 Map。其中 key 是您的整数值, value 是满足该元素的次数的计数器。

标签: java arrays collections guava colt


【解决方案1】:
public class commonvalue {

  
   Public static void MyMethod(){
        
       Set<integer> S1 = new set<integer>{1,3,5};
        Set<integer> S2 = new set<integer>{1,6,7,9,3};
        Set<integer> S3 = new set<integer>{1,3,10,11};
           
            s2.retainall(s1);
            s3.retainall(s2);
       
       system.debug(s3);
}
}

【讨论】:

  • 请解释这段代码的工作原理并回答问题。
  • 代码转储不能提供好的答案。你应该解释如何和为什么这可以解决他们的问题。我推荐阅读,“How do I write a good answer?"。这可以帮助未来的用户学习并最终将这些知识应用到他们自己的代码中。当代码被解释时,你也可能会得到用户的积极反馈/赞成。
【解决方案2】:

使用 Java 8

ArrayList retain = list1.stream()
                     .filter(list2::contains).filter(list3::contains).collect(toList())

【讨论】:

  • 我认为这应该被接受,虽然我认为正确的形式是:ArrayList retain = list1.stream().filter(list2::contains).collect(Collectors.toCollection(ArrayList::new));
  • 这仅适用于 3 个列表。我认为问题是关于任意数量的列表。
【解决方案3】:

你可以使用Guava提供的Set的交集方法,这里有一个小例子:

public <T> Set<T> intersection(List<T>... list) {
    Set<T> result = Sets.newHashSet(list[0]);
    for (List<T> numbers : list) {
        result = Sets.intersection(result, Sets.newHashSet(numbers));
    }
    return result;
}

希望对你有帮助

【讨论】:

  • 这对我很有帮助,感谢您的解决方案。我想知道为什么这是不可接受的,无论如何谢谢
【解决方案4】:

我们可以使用retainAll method of Collections。我用第一个数组列表初始化了我的 commons 数组列表,并为每个剩余的数组列表调用了它。

    List<List<Integer>> lists = new ArrayList<List<Integer>>();
    lists.add(new ArrayList<Integer>(Arrays.asList(1, 3, 5)));
    lists.add(new ArrayList<Integer>(Arrays.asList(1, 6, 7, 9, 3)));
    lists.add(new ArrayList<Integer>(Arrays.asList(1, 3, 10, 11)));

    List<Integer> commons = new ArrayList<Integer>();
    commons.addAll(lists.get(1));
    for (ListIterator<List<Integer>> iter = lists.listIterator(1); iter.hasNext(); ) {
        commons.retainAll(iter.next());
    }

    System.out.println(commons);
    System.out.println(lists.get(1));

【讨论】:

  • 你为什么从索引 1 开始?我们不应该从 0 开始吗​​?
【解决方案5】:
public class ArrayListImpl{
  public static void main(String s[]){
    ArrayList<Integer> al1=new ArrayList<Integer>();
     al1.add(21);al1.add(23);al1.add(25);al1.add(26);
    ArrayList<Integer> al2=new ArrayList<Integer>();
     al2.add(15);al2.add(16);al2.add(23);al2.add(25);
     ArrayList Al3=new ArrayList<Integer>();
     al3.addAll(al1);
      System.out.println("Al3 Elements :"+al3);
     al3.retainAll(al2); //Keeps common elements of (al1 & al2) & removes remaining elements
       System.out.println("Common Elements Between Two Array List:"+al3);  
}
}

【讨论】:

    【解决方案6】:

    如果您正在寻找返回所有列表中存在的元素的函数,

    那么直接而简单的方法是建立一个统计信息 { }

    这里的条件是同一个列表中没有重复,

    private Set<Integer> getCommonElements(ArrayList<Integer[]> idList)
    {
    
        MapList<Integer,Short> stat = new MapList<Integer,Short>();
    
        // Here we count how many times each value occur
        for (int i = 0; i < idList.size(); i++)
        {
            for (int j = 0; j < idList.get(i).size; j++)
            {
                if (stat.containsKey(idList.get(i)[j]))
                {
                    stat.set(idList.get(i)[j], stat.get(idList.get(i)[j])+1);
                }
                else
                {
                    stat.add(idList.get(i)[j], 1);
                }
            }
        }
    
        // Here we only keep value that occured in all lists
        for (int i = 0; i < stat.size(); i++)
        {
            if (stat.get(i) < idList.size())
            {
                stat.remove(i);
                i--;
            }
        }
    
        return stat.keySet();
    }
    

    【讨论】:

    • 与 C# 不同,在 Java 中,您不能将原语指定为泛型类型。所以不要使用Set&lt;int&gt;,而是使用Set&lt;Integer&gt;。
    • 感谢您的信息,福阿德
    【解决方案7】:

    您可以将列表转换为集合,然后使用Set.retainAll 方法在不同集合之间进行交集。 与所有集合相交后,就剩下公共元素,您可以将结果集合转换回列表。

    【讨论】:

    • 它仍然符合您的要求 - 您可以将每个列表转换为 Set(HashSet 可以将 Collection 作为构造函数参数),进行交集,并将相交集转换回列表。这个解决方案是 O(n),而对每个列表进行排序和比较是 O(n*log(n)),将每个项目与其他项目进行比较是 O(n^2)。
    • @AmirKost 转换为Set(不是LinkedHashSet)将失去列表的顺序。
    猜你喜欢
    • 2010-12-11
    • 2016-07-06
    • 1970-01-01
    • 2023-02-02
    • 2013-04-17
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多