【问题标题】:Get a list of combinations of lists' elements获取列表元素组合的列表
【发布时间】:2017-05-31 02:33:44
【问题描述】:

假设我有 3 个列表:['q','w'], ['a','s'], ['z','x']。如何从这些列表中获取可能组合的列表?所以我得到一个列表 [['q','a','z'],['q','s','z']] 等等。我为两个列表做了一个方法,但无法为 N 个列表计算一个:

static <E> ArrayList combine(ArrayList<E> one,ArrayList<E> two)
{
    ArrayList<ArrayList<E>> combs=new ArrayList<ArrayList<E>>();
    for(E e:one)
    {
        for(E e2:two)
        {
            ArrayList ps=new ArrayList();
            ps.add(e);
            ps.add(e2);
            combs.add(ps);
        }
    }
    return combs;
}

我发现这是由 Guava 的 Sets.cartesianProduct 完成的。

【问题讨论】:

    标签: java combinatorics


    【解决方案1】:

    对于懒人(使用番石榴):

    Set<List<String>> result = Sets.cartesianProduct(
                    ImmutableSet.of("q", "w"),
                    ImmutableSet.of("a", "s"),
                    ImmutableSet.of("z", "x")
            );
    
    System.out.println(result);
    

    输出:

    [ [q, a, z], [q, a, x], [q, s, z], [q, s, x], [w, a, z], [w, a, x], [w, s, z], [w, s, x] ]

    【讨论】:

      【解决方案2】:

      您需要 N 个嵌套循环,这使得它变得困难。

      您可以使用递归来实现这一点。

      static <E> ArrayList combine(ArrayList<E> soFar, ArrayList<E>... lists)
      {
          // Rather than constantly making and remaking this list could just use one
          // and pass it around and add stuff to it. This works though.
          ArrayList<ArrayList<E>> combs=new ArrayList<ArrayList<E>>();
      
          // Loop through the first list looking for elements
          for(E e:lists[0])
          {
             // Create a new List to build this combination
             ArrayList<E> temp = new ArrayList<>(soFar);
             // Add this element to the combination
             temp.add(e);
             // If there are more lists recurse down
             if (lists.length > 1) {
                 // Use recursion to add all combinations of the remaining lists
                 combs.addAll(combine(temp, lists.subList(1)));
             } else {
                 // There are no more lists so we are done, add temp to the combos
                 combs.add(temp);
             }
          }
          return combs;
      }
      
      
      // Call this method to start things going, the other one should probably be private
      static <E> ArrayList combine(ArrayList<E>... lists)
          return combine(new ArrayList<E>(), lists);
      }
      

      【讨论】:

      • 如何调用lists.subList?那不是数组吗?
      • 好点,这里的所有代码都是直接输入的,所以需要一些调整。 :) 使用 docs.oracle.com/javase/7/docs/api/java/util/… 或者只是传递整个数组并使用 soFar.size() 作为数组的索引。 (第二种方法会更有效)。
      【解决方案3】:

      您可能想看看https://github.com/javagl/Combinatorics/blob/master/src/main/java/de/javagl/utils/math/combinatorics/MixedRangeCombinationIterable.java 类(“独立”类,只需复制并插入到您的项目中)

      示例用法:

      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.List;
      
      public class Combinations
      {
          public static void main(String[] args)
          {
              List<List<Character>> lists = new ArrayList<List<Character>>();
              lists.add(Arrays.asList('q','w'));
              lists.add(Arrays.asList('a','s'));
              lists.add(Arrays.asList('z','x'));
      
              MixedRangeCombinationIterable<Character> iterable = 
                  new MixedRangeCombinationIterable<Character>(lists);
              for (List<Character> element : iterable)
              {
                  System.out.println(element);
              }
          }
      }
      

      您实际上是在计算输入集 http://en.wikipedia.org/wiki/Cartesian_product 的元素

      【讨论】:

        【解决方案4】:

        您可以使用构造函数 (Parameters ...) 创建一个内部类,因此您可以列出处理所有组合的此类

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-04-12
          • 1970-01-01
          • 2021-03-02
          • 1970-01-01
          • 2019-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多