How to Get All Combinations from Multiple Arrays

How to get all combinations from multiple arrays?

How many combinations are there?

So first the question how many combinations are there? And the answer is you have to multiply the amount of every array with each other.

So (c = amount1):

carray 1 * carray 2 * ... * carray n

And specific for your example:

carray 1 * carray 2 * carray 3 = 2 * 2 * 2 = 8

*1 And if you wonder why I chose c for amount, because of the function count() in php

Getting all combinations together

How do we get now all combinations with the amount of arrays, which we have?

We loop through all our combinations, which we already have(Starting off with one combination, an "empty combination" ($combinations = [[]];)), and for each combination we go through our next data array and combine each combination with each input data to a new combination.

Now we do this until we get the desired length for each combination.

So as an example:

Array with the elements (Empty array is '[]'):

[
[1, 2],
[3, 4]
]


                               //↓ new combinations for the next iteration

array NAN*:

Combinations:
- [] │ -> []

array 1 [1,2]: ┌─────────────┤
│ │
Combinations: v v
- [] + 1 │ -> [1]
- [] + 2 │ -> [2]

array 2 [3,4]: ┌─────────────┤
│ │
Combinations: v v
- [] + 3 │ -> [3]
- [] + 4 │ -> [4]
- [1] + 3 │ -> [1,3] //desired length 2 as we have 2 arrays
- [1] + 4 │ -> [1,4] //desired length 2 as we have 2 arrays
- [2] + 3 │ -> [2,3] //desired length 2 as we have 2 arrays
- [2] + 4 │ -> [2,4] //desired length 2 as we have 2 arrays
//↑ All combinations here

* NAN: not a number

So as you can see in the above example we now have all combinations with the length of the amount of all arrays which we have.

But to get only the combinations with the desired length we are overwriting the result array each iteration, so that at the end only the combinations with the expected length are in the results array.

Code:

<?php

$array1 = array(1,2);
$array2 = array(4,5);
$array3 = array(7,8);

$combinations = [[]];
$data = [
$array1,
$array2,
$array3,
];
$length = count($data);

for ($count = 0; $count < $length; $count++) {
$tmp = [];
foreach ($combinations as $v1) {
foreach ($data[$count] as $v2)
$tmp[] = array_merge($v1, [$v2]);

}
$combinations = $tmp;
}

print_r($combinations);

?>

output:

Array
(
[0] => Array
(
[0] => 1
[1] => 4
[2] => 7
)
//...
[7] => Array
(
[0] => 2
[1] => 5
[2] => 8
)

)

For associative arrays you only have to do a slight modification, which is:

  1. First assign the arrays keys to a variable with array_keys(), e.g.

    $keys = array_keys($data);
  2. Use the keys in the second foreach loop to access the data array, means from:

    foreach ($data[$count] as $v2)

    to:

    foreach ($data[$keys[$count]] as $v2)

How can I create every combination possible for the contents of two arrays?

A loop of this form

combos = [] //or combos = new Array(2);

for(var i = 0; i < array1.length; i++)
{
for(var j = 0; j < array2.length; j++)
{
//you would access the element of the array as array1[i] and array2[j]
//create and array with as many elements as the number of arrays you are to combine
//add them in
//you could have as many dimensions as you need
combos.push(array1[i] + array2[j])
}
}

JavaScript - Generating combinations from n arrays with m elements

Here is a quite simple and short one using a recursive helper function:

function cartesian(...args) {
var r = [], max = args.length-1;
function helper(arr, i) {
for (var j=0, l=args[i].length; j<l; j++) {
var a = arr.slice(0); // clone arr
a.push(args[i][j]);
if (i==max)
r.push(a);
else
helper(a, i+1);
}
}
helper([], 0);
return r;
}

Usage:

cartesian([0,1], [0,1,2,3], [0,1,2]);

To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.

Combination of elements of multiple arrays

This is my attempt at getting combinations from multiple arrays(containers).

 private List<List<T>> getCombination(int currentIndex, List<TempContainer<T>> containers) {
if (currentIndex == containers.size()) {
// Skip the items for the last container
List<List<T>> combinations = new ArrayList<List<T>>();
combinations.add(new ArrayList<T>());
return combinations;
}
List<List<T>> combinations = new ArrayList<List<T>>();
TempContainer<T> container = containers.get(currentIndex);
List<T> containerItemList = container.getItems();
// Get combination from next index
List<List<T>> suffixList = getCombination(currentIndex + 1, containers);
int size = containerItemList.size();
for (int ii = 0; ii < size; ii++) {
T containerItem = containerItemList.get(ii);
if (suffixList != null) {
for (List<T> suffix : suffixList) {
List<T> nextCombination = new ArrayList<T>();
nextCombination.add(containerItem);
nextCombination.addAll(suffix);
combinations.add(nextCombination);
}
}
}
return combinations;
}

The method takes a list of containers with items. e.g. Container 1 will have [a,b] and Container 2 will have [c,d,e]. The method can take any number of containers.
// The container class is declared as follows:

public class TempContainer<T> {
private List<T> items;
public void setItems(List<T> items) {
this.items = items;
}

public List<T> getItems() {
return items;
}
}

Call this method as follows:

List<String> list1 = new ArrayList<String>();
list1.add("1");
list1.add("2");
List<String> list2 = new ArrayList<String>();
list2.add("3");
list2.add("4");
list2.add("5");
TempContainer container1 = new TempContainer();
container1.setItems(list1);
TempContainer container2 = new TempContainer();
container2.setItems(list2);
List<TempContainer> containers = new ArrayList<TempContainer>(2);
containers.add(container1);
containers.add(container2);
// Get combinations
List<List<T>> combinations = getCombination(0, containers);

Finding all possible combinations of multiple arrays (where all combinations also include all items in the array)

It isn't totally clear what your desired outcome is, but I think itertools.product() is what you are looking for...

from itertools import product

five=["fivea","fiveb","fivec","fived"]
six=["sixa","sixb","sixc","sixd"]
seven=["sevena","sevenb","sevenc","sevend"]

my_lists = [five, six, seven]

for item in product(*my_lists):
print(item)

Yields

('fivea', 'sixa', 'sevena')
('fivea', 'sixa', 'sevenb')
('fivea', 'sixa', 'sevenc')
('fivea', 'sixa', 'sevend')
('fivea', 'sixb', 'sevena')
('fivea', 'sixb', 'sevenb')
('fivea', 'sixb', 'sevenc')
('fivea', 'sixb', 'sevend')
('fivea', 'sixc', 'sevena')
('fivea', 'sixc', 'sevenb')
('fivea', 'sixc', 'sevenc')
('fivea', 'sixc', 'sevend')
('fivea', 'sixd', 'sevena')
('fivea', 'sixd', 'sevenb')
('fivea', 'sixd', 'sevenc')
('fivea', 'sixd', 'sevend')
('fiveb', 'sixa', 'sevena')
('fiveb', 'sixa', 'sevenb')
...
('fived', 'sixd', 'sevend')

Using permutations of all elements... with shortened lists

from itertools import permutations as p

five=["fivea","fiveb"]
six=["sixa","sixb","sixc"]
seven=["sevena","sevenb"]

my_lists = [five, six, seven]

# flatten it out...
my_items = [item for sublist in my_lists for item in sublist ]

print(my_items)

for perm in p(my_items, len(my_items)):
print(perm)

Generate combinations of values from multiple arrays

If you want all the possible combinations, there's no alternative other than iterating through each of the elements for all arrays.

Creating hashes is not difficult either.

Try this.

a = [1, 2, 3, 4, 5]
b = ['A', 'B', 'C', 'D', 'E']
c = ['J', 'K', 'L', 'M', 'N']
d = ['v', 'w', 'x', 'y', 'z']

result = []

a.each do |a_elem|
b.each do |b_elem|
c.each do |c_elem|
d.each do |d_elem|
result << {a: a_elem, b: b_elem, c: c_elem, d: d_elem}
end
end
end
end

puts "#{result}"

I believe this is what you are looking for.

Get all combinations of list multiple arrays

Here is an answer using list-comprehension

import itertools
import math

def iden(x):
return x

def log(x):
return math.log(x)

def exp(x):
return 1/(1+math.exp(-x))

X = [1, 2, 3]
funcs = [iden, log, exp]

def apply(functions, values):
return [func(val) for func,val in zip(functions, values)]

values = [apply(f, X) for f in itertools.product(funcs, repeat=len(funcs))]

The apply function seemed useful. If you don't want it, then this will do

values = [[func(val) for func,val in zip(f, X)] for f in itertools.product(funcs, repeat=len(funcs))]

Sample output

[1, 2, 3] # (iden, iden, iden)
[1, 2, 1.0986122886681096] # (iden, iden, log)
[1, 2, 0.95257412682243336] # (iden, iden, exp)
[1, 0.69314718055994529, 3] # (iden, log, iden)

Find all combinations consisting of one row per multiple arrays

Adapted from https://stackoverflow.com/a/49445693/7207392

import numpy as np
import operator as op
import itertools as it

def cartesian_product_pp(arrays, out=None):
la = len(arrays)
h, w = zip(*map(op.attrgetter('shape'), arrays))
w = np.fromiter(it.chain([0], w), int, la+ 1)
W = w.cumsum()
h = *h, W[la]
dtype = np.result_type(*arrays)
arr = np.empty(h, dtype=dtype)
arrs = *it.accumulate(it.chain((arr,), it.repeat(0, la-1)), np.ndarray.__getitem__),
idx = slice(None), *it.repeat(None, la-1)
for i in range(la-1, 0, -1):
arrs[i][..., W[i]:W[i+1]] = arrays[i][idx[:la-i]]
arrs[i-1][1:] = arrs[i]
arr[..., W[0]:W[1]] = arrays[0][idx]
return arr.reshape(-1, W[la])

# example
a = np.r_[:3].reshape(1, 3)
b = np.r_[5:20].reshape(3, 5)
c = np.r_[17:38].reshape(3, 7)
p = cartesian_product_pp([a, b, c])

Output:

>>> p
array([[ 0, 1, 2, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23],
[ 0, 1, 2, 5, 6, 7, 8, 9, 24, 25, 26, 27, 28, 29, 30],
[ 0, 1, 2, 5, 6, 7, 8, 9, 31, 32, 33, 34, 35, 36, 37],
[ 0, 1, 2, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23],
[ 0, 1, 2, 10, 11, 12, 13, 14, 24, 25, 26, 27, 28, 29, 30],
[ 0, 1, 2, 10, 11, 12, 13, 14, 31, 32, 33, 34, 35, 36, 37],
[ 0, 1, 2, 15, 16, 17, 18, 19, 17, 18, 19, 20, 21, 22, 23],
[ 0, 1, 2, 15, 16, 17, 18, 19, 24, 25, 26, 27, 28, 29, 30],
[ 0, 1, 2, 15, 16, 17, 18, 19, 31, 32, 33, 34, 35, 36, 37]])

Timings for this, @B.M.'s and @Bazingaa's approaches:

>>> timeit(lambda: cartesian_product_pp([a,b,c]), number=1000)*1000
15.173833002336323
>>> timeit(lambda: combine([a,b,c]), number=1000)*1000
31.1394709860906
>>> timeit(lambda: np.array([np.hstack((i, j, k)) for i in a for j in b for k in c]), number=1000)*1000
51.15771805867553


Related Topics



Leave a reply



Submit