Basically you want to generate all the possible subsets containing 2 elements of your original set.
Short answer:
# With m = 4
c = np.multiply(*np.add(np.triu_indices(4,1),1))
General solution for any input array:
If using itertools is an option then you can use:
import numpy as np
import itertools
x = list(itertools.combinations([1,2,3,4], 2))
c = np.prod(x,-1)
c output:
array([ 2, 3, 4, 6, 8, 12])
From the doc:
itertools.combinations(iterables,r) : return r-length tuples in
sorted order with no repeated elements.
And the number of elements in c correspond to the binomial coefficient C(n,k): n choose k, where n = len([1,2,3,4]) and k = 2.
Noticed that itertools.combinations() only hide the for loops, but since there is no closed-form formula for this problem a for loop is inevitable.
Numpy only solution:
In your specific case, where your iterable are the suit of n positive integers [1,2,3,4,...,n] then you can noticed that the positive indice of an upper triangle 2D matrice of length n-1 will produce the same result as combinations so:
# Number of elements in your array
n = 4
# Upper triangular matrice
x = np.triu(np.ones([n-1,n-1]))
# Get the result
c = np.prod(np.argwhere(x)+np.arange(1,3),-1)
And again c output:
array([ 2, 3, 4, 6, 8, 12])
Or (with the help of @Nachikel, I wasn't aware of the existence of np.triu_indices()) the one liner:
c = np.multiply(*np.add(np.triu_indices(4,1),1))
Benchmarking:

and also with itertools:

The code:
import numpy as np
import itertools
import timeit
import matplotlib.pyplot as plt
def itertools1(m):
x = list(itertools.combinations(np.arange(1,m+1), 2))
np.prod(x,-1)
def numpy1(m):
n = m-1
x = np.triu(np.ones([n,n]))
np.prod(np.argwhere(x)+np.arange(1,3),-1)
def numpy2(m):
np.multiply(*np.add(np.triu_indices(m,1),1))
def benchmark_time(m):
SETUP_CODE = '''
from __main__ import numpy1
from __main__ import numpy2
from __main__ import itertools1
'''
x = np.zeros([3,len(m)])
for ind, m in enumerate(m):
print('For m = {}'.format(m))
TEST_CODE = '''
itertools1({})
'''.format(m)
# timeit.repeat statement
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = 10,
number = 50)
x[0,ind] = np.average(times)
print('Itertools1 give:\t{} s'.format(np.round(np.average(times),3)))
TEST_CODE = '''
numpy1({})
'''.format(m)
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = 10,
number = 50)
x[1,ind] = np.average(times)
print('Numpy1 give:\t\t{} s'.format(np.round(np.average(times),3)))
TEST_CODE = '''
numpy2({})
'''.format(m)
times = timeit.repeat(setup = SETUP_CODE,
stmt = TEST_CODE,
repeat = 10,
number = 50)
x[2,ind] = np.average(times)
print('Numpy2 give:\t\t{} s\n'.format(np.round(np.average(times),3)))
return x
m = np.arange(10,150,10)
x = benchmark_time(m)
plt.plot(m,x.T)
plt.legend(('itertools', 'numpy triu', 'numpy triu_indices'))
plt.xlabel('m')
plt.ylabel('sec')
plt.show()