Question: I have a strange situation here. I have that table structure

[![enter image description here](https://i.stack.imgur.com/Vv50a.png)](https://i.stack.imgur.com/Vv50a.png)

Whenever Cost is 0 I need to put Line 2 description together with Line 1 description.

I should get this at the end

[![enter image description here](https://i.stack.imgur.com/rgYD5.png)](https://i.stack.imgur.com/rgYD5.png)

I am trying to do this in c# but failing miserably.

So far, this is where I am at

[![enter image description here](https://i.stack.imgur.com/ZDcd7.png)](https://i.stack.imgur.com/ZDcd7.png)

Answer: 
Numpy's ufuncs all have an [`outer`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.outer.html?highlight=outer#numpy.ufunc.outer) method to perform operations "cross-wise" on two arrays. So to avoid most intermediate calculation and vectorize as far as possible:

```
def f(M, a):
    return 2 * M / np.add.outer(a, a)

```

---

**Answer for the old version of the question (left, because it's still useful)**:

For such things, I found it best to always work in steps, and try to find the right [`einsum`](https://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html?highlight=einsum#numpy.einsum) expression.

```
# the definition given in the original question,
# before the z / (y + x) update
def f0():
    d = np.empty((3,3))
    for i in range(len(a)):
        x = a[i]
        for j in range(len(a)):
            y = a[j]
            z = M[i][j]
            d[i][j] = 2 * x/(y+z)
    return d

# rewrite things inlined
def f1():
    d = np.empty((3,3))
    for i in range(len(a)):
        for j in range(len(a)):
            d[i, j] = 2 * a[i]/(a[j] + M[i, j])
    return d

# factor out broadcasting
def f2():
    d = np.empty((3,3))
    for i in range(len(a)):
        m = a + M[i, :]
        for j in range(len(a)):
            d[i,j] = 2 * a[i]/m[j]
    return d

# more broadcasting
def f3():
    d = np.empty((3,3))
    m = a + M
    for i in range(len(a)):
        for j in range(len(a)):
            d[i,j] = 2 * a[i]/m[i,j]
    return d

# now turn loops into einsums
def f4():
    d = np.empty((3,3))
    m = 1/(a + M)
    d[:,:] = 2 * np.einsum('i,ij->ij', a, m)
    return d

# collect everything
def f5():
    return np.einsum('i,ij->ij', a, 2 / (a + M))

```
Apart from numpy-vectorization using Numba would also a simple and performant method, to speed up code with loops.
**Example**

```
import numpy as np
import numba as nb

@nb.njit(fastmath=True,error_model="numpy",parallel=True)
def calc(a,M):
    d=np.empty((a.shape[0],a.shape[0]))
    for i in nb.prange(a.shape[0]):
        x = a[i]
        for j in range(a.shape[0]):
            y = a[j]
            z = M[i,j]
            d[i,j] = 2. * z/(y+x)
    return d

```

**Timings**

```
M=np.random.rand(200,200)
a=np.random.rand(200)

d=calc(a,M) #first call takes longer due to compilation overhead
%timeit d=calc(a,M)
#parallel=True there is only quite limited speedup because of the small problem (200x200)
#11 µs ± 51 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
#parallel=False
#21.2 µs ± 191 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

#pure numpy solution (hpaulj)
%timeit d = 2 * M/(a[:,None]+a[None,:])
#75.7 µs ± 386 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

#without compilation
#20.8 ms ± 500 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

```