简体   繁体   English

从给定的字符串数组创建多个 arrays

[英]Create multiple arrays from a given string array

I have an array of unique strings from which i need to create all possible arrays with the same length.我有一个唯一字符串数组,我需要从中创建所有可能的具有相同长度的 arrays。

String[] str = {"Belgium", "France", "Germany"};

The goal is to create a list of arrays which have every possible value from above array at each index,目标是创建一个 arrays 列表,其中每个索引处都有上述数组中的每个可能值,

[Belgium, Belgium, Belgium]
[Belgium, Belgium, France]
[Belgium, Belgium, Germany]
[Belgium, France, Belgium]
[Belgium, France, France]
[Belgium, France, Germany]
[Belgium, Germany, Belgium]
[Belgium, Germany, France]
[Belgium, Germany, Germany]
[France, Belgium, Belgium]

....

[Germany, Germany, France]
[Germany, Germany, Germany]

My code to create this looks like我创建这个的代码看起来像

static List<String[]> getAllAllocations(String[] input){
    List<String[]> result = new ArrayList<>();
    if(input.length == 2){
        for(int i = 0; i < 2; i++){
            for(int j = 0; j < 2; j++){
                result.add(new String[]{input[i], input[j]});
            } 
        }
    }
    else if(input.length == 3){
        for(int i = 0; i < 3; i++){
            for(int j = 0; j < 3; j++){
                for(int k = 0; k < 3; k++){
                    result.add(new String[]{input[i], input[j], input[k]});
                }
            } 
        }
    }
    else if(input.length == 4){
        for(int i = 0; i < 4; i++){
            for(int j = 0; j < 4; j++){
                for(int k = 0; k < 4; k++){
                    for(int m = 0; m < 4; m++){
                        result.add(new String[]{input[i], input[j], input[k], input[m]});
                    }
                }
            } 
        }
    }
    //else if(input.length == 5) similar code with 5 for loops
    //else if(input.length == 6) similar code with 6 for loops
    //else if(input.length == 7) similar code with 7 for loops
    //else if(input.length == 8) similar code with 8 for loops
    return result;
}

The array will have a variable length between 2 and 8. How can I dynamicaly create the for loops instead of chaining the if-else checks or any other way to do this in an elganter way than I did above?该数组将具有 2 到 8 之间的可变长度。如何动态创建 for 循环,而不是链接 if-else 检查或以比我上面所做的更优雅的方式执行此操作的任何其他方式?

Recursive solution递归解决方案

public static List<String[]> getAllAllocations(String[] input) {
    List<String[]> result=new ArrayList<String[]>();
    getAllAllocations(result, input, new String[input.length], 0);
    return result;
}

public static void getAllAllocations(List<String[]> result, String[] input, String[] current, int depth) {
    if (depth>=input.length) {
        result.add(current.clone());
    } else {
        for (int i=0;i<input.length;i++) {
            current[depth]=input[i];
            getAllAllocations(result, input, current, depth+1);
        }
    }
}

Iterative solution迭代解决方案

public static List<String[]> getAllAllocations2(String[] input) {
    List<String[]> result=new ArrayList<String[]>();
    
    int[] counters=new int[input.length];
    
    boolean done=false;
    while (!done) {
        
        String[] comb=new String[input.length];
        for (int i=0;i<comb.length;i++) {
            comb[i]=input[counters[i]];
        }
        result.add(comb);

        done=true;
        for (int i=0;i<counters.length;i++) {
            counters[i]++;
            if (counters[i]>=input.length) {
                counters[i]=0;
            } else {
                done=false;
                break;
            }
        }
    }
    
    return result;
}

You can use map and reduce approach:您可以使用mapreduce方法:

  1. map - first prepare the lists of arrays List<String[]> . map - 首先准备 arrays List<String[]>的列表。 An array of three elements becomes three lists of singleton arrays:三个元素的数组变成了 singleton arrays 的三个列表:

     list1: [[Belgium], [France], [Germany]] list2: [[Belgium], [France], [Germany]] list3: [[Belgium], [France], [Germany]]
  2. reduce - then multiply these lists sequentially one by one and get the Cartesian product . reduce - 然后将这些列表依次一一相乘,得到笛卡尔积 Two steps of reduction for three lists:三个列表的两个减少步骤:

     list1: [[Belgium], [France], [Germany]] list2: [[Belgium], [France], [Germany]] ------ sum1: [[Belgium, Belgium], [Belgium, France], ..., [Germany, Germany]]
     sum1: [[Belgium, Belgium], [Belgium, France], ..., [Germany, Germany]] list3: [[Belgium], [France], [Germany]] ------ total: [[Belgium, Belgium, Belgium], [Belgium, Belgium, France], ...]

Try it online! 在线尝试!

public static void main(String[] args) {
    String[] str = {"Belgium", "France", "Germany"};
    cartesianProduct(str).forEach(arr->System.out.println(Arrays.toString(arr)));
}
static List<String[]> cartesianProduct(String[] input) {
    return IntStream.range(0, input.length)
            // Stream<List<String[]>>
            .mapToObj(i -> Arrays.stream(input)
                    .map(str -> new String[]{str})
                    .collect(Collectors.toList()))
            // stream of lists to a single list
            .reduce((list1, list2) -> list1.stream()
                    .flatMap(arr1 -> list2.stream()
                            .map(arr2 -> Stream.of(arr1, arr2)
                                    .flatMap(Arrays::stream)
                                    .toArray(String[]::new)))
                    .collect(Collectors.toList()))
            .orElse(Collections.emptyList());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM