【问题标题】:Java Find All Possible Combinations From Columns [duplicate]Java从列中查找所有可能的组合[重复]
【发布时间】:2016-05-31 22:14:42
【问题描述】:

我有一个算法,它通过从每一列中取一个项目来返回所有可能的组合(这里选择汤、面条和浇头)。

有没有更有效和动态的方法来做到这一点?为了使 findAllCombinations 方法起作用,我需要知道有多少列并对它们进行硬编码。

有效组合: 【豆瓣汤、乌冬面、鱼块】、【麻辣汤、拉面、火腿】、……

ArrayList<ArrayList<String>> listOfLists = Lists.newArrayList();
listOfLists.add(Lists.newArrayList("Original Soup", "Spicy Soup", "Watercress Soup", "Thai Spicy Soup", "Malaysia Spicy Soup"));
listOfLists.add(Lists.newArrayList("Udon", "Ramen", "Egg Noodle", "Flat Rice Noodle", "Vermicelli", "Instant Noodle"));
listOfLists.add(Lists.newArrayList("Fish Cube", "Fish Ball", "Ham", "Squid", "Seaweed"));

ArrayList<ArrayList<String>> combo = findAllCombinations(listOfLists);


private ArrayList<ArrayList<String>> findAllCombinations(ArrayList<ArrayList<String>> arrays){
    ArrayList<ArrayList<String>> combinations = new ArrayList<>();
    for(String item1: arrays.get(0)){
        for(String item2: arrays.get(1)){
            for(String item3: arrays.get(2)){
                ArrayList<String> temp = new ArrayList<String>() {
                    {
                        add(item1);
                        add(item2);
                        add(item3);
                    }
                };
                combinations.add(temp);
            }
        }
    }
    return combinations;
}

【问题讨论】:

  • 为什么要跳过第二个数组的第一个成员和第三个数组的前两个成员?
  • @LostAndConfused 你似乎有点迷茫和困惑。
  • @LostAndConfused 他不是,他正在选择第一个、第二个和第三个数组
  • 哈哈哈哈哈。谢谢你。不知道我发生了什么事。 :) 没有乌冬面作为选项的想法让我感到害怕,超出了逻辑和理性的范畴。 :O :D

标签: java arrays algorithm combinations


【解决方案1】:

如果您不使用番石榴并且需要/想要自己推出,那么就可以了(代码如下)。

这个想法是将组合的数量计算为列表大小的乘积,然后从 0 迭代到 number_of_combinations-1,并将该范围内的每个整数转换为不同的组合。

import java.util.ArrayList;
import java.util.Arrays;

public class Tester {

private static ArrayList<ArrayList<String>> findAllCombinations(ArrayList<ArrayList<String>> arrays){
    final ArrayList<ArrayList<String>> combinations = new ArrayList<>();
    int combinationCount = 1;
    for ( final ArrayList<String> als : arrays ) {
        combinationCount *= als.size();
    }

    for ( int i = 0; i < combinationCount; i++ ) {
        int combinationIndex = i;
        final ArrayList<String> oneCombination = new ArrayList<String>();
        for ( final ArrayList<String> als : arrays ) {
            int index = combinationIndex % als.size();
            oneCombination.add(als.get(index));
            combinationIndex = (combinationIndex - index) / als.size();
        }
        combinations.add(oneCombination);
    }
    return combinations;
}

public static void main(String[] args) {

final ArrayList<ArrayList<String>> listOfLists = new ArrayList<ArrayList<String>>();
listOfLists.add(new ArrayList<String>(Arrays.asList(new String[] {"Original Soup", "Spicy Soup", "Watercress Soup", "Thai Spicy Soup", "Malaysia Spicy Soup"})));
listOfLists.add(new ArrayList<String>(Arrays.asList(new String[] {"Udon", "Ramen", "Egg Noodle", "Flat Rice Noodle", "Vermicelli", "Instant Noodle"})));
listOfLists.add(new ArrayList<String>(Arrays.asList(new String[] {"Fish Cube", "Fish Ball", "Ham", "Squid", "Seaweed"})));

ArrayList<ArrayList<String>> combo = findAllCombinations(listOfLists);
System.out.println(combo);
System.out.println("Generated " + combo.size() + " combinations");
}

}

【讨论】:

  • OP 显然在使用 Guava。
  • 是的,我知道。但是根据帖子的标题,也许不是每个通过搜索找到这个问题的人都在使用 Guava。如果这是 StackOverflow “犯规”,我可以删除或修改我的答案。
  • 你的答案没问题(除了它比OP的解决方案更复杂);我只是在评论你的第一句话。旁注:1) Arrays.asList() 接受可变参数,2) 将其结果传递给 new ArrayList 有点过分,但如果您想保留 OP 的方法签名,技术上需要这样做。跨度>
  • 有趣的答案;我不会想到先计算数字。
【解决方案2】:

如果您将结构调整为集合列表而不是列表列表,则可以使用 Guava 的 Sets.cartesianProduct()

List<Set<String>> listOfSets = Lists.newArrayList();
listOfSets.add(Sets.newHashSet("Original Soup", "Spicy Soup", "Watercress Soup", "Thai Spicy Soup", "Malaysia Spicy Soup"));
listOfSets.add(Sets.newHashSet("Udon", "Ramen", "Egg Noodle", "Flat Rice Noodle", "Vermicelli", "Instant Noodle"));
listOfSets.add(Sets.newHashSet("Fish Cube", "Fish Ball", "Ham", "Squid", "Seaweed"));

Set<List<String>> combo = Sets.cartesianProduct(listOfSets);

如果订购很重要,您可以使用LinkedHashSet

编辑:从第 19 版开始,Guava 有 Lists.cartesianProduct(),它应该完全符合您的要求。

【讨论】:

  • 我不确定你所说的使用 LinkedHashSet 是什么意思。
  • LinkedHashSet listOfSets = new LinkedHashSet(); 将不起作用。
  • @PandaTank 我的意思是像listOfSets.add(new LinkedHashSet&lt;&gt;(Arrays.asList("Fish Cube", "Fish Ball", "Ham", "Squid", "Seaweed")));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-04
  • 1970-01-01
  • 2016-10-16
相关资源
最近更新 更多