[英]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:您可以使用
map
并reduce
方法:
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]]
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], ...]
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.