# Is Table the only functional way to construct nested loops in Mathematica?

Suppose you have a cubic box containing identical particles and you want to compute the distances between each particle and every other particle in the box without double-counting (i.e., if you've computed the distance between particles 1 and 2, you don't want to repeat the computation for particles 2 and 1 when looping through 2). In C-style languages you could do something like:

for ( int i = 0; i < nparticles - 1; i++ )
{
for ( int j = i + 1; j < nparticles; j++ )
{
//calculate distance and some other stuff
}
}


In Mathematica you could do the following:

  ParallelTable[Distance[coord[[i]], coord[[j]], z],
{i, 1, nparticles - 1}, {j, i + 1, nparticles}]


Where Distance is a function that takes in the positions of two particles and a boxsize variable and spits-out the distance between them. Is there a better, more elegant Mathematica-way to achieve this? I've tried using Outer to no success.

To give a specific example:

coord = {{0.336384, 0.0132788, 0.895366}, {0.531722,
0.703736, -0.626689}, {1.3723, 0.191368,
0.930669}, {1.92434, -0.561288, 0.537316}, {2.48175, 1.34384,
0.368834}, {1.91778, 0.489024, -0.138269}, {3.22166, 1.46687,
1.16486}, {3.16976, -0.134968, 1.46946}, {3.31118, 0.625944,
0.0811552}, {4.39825, 1.03799,
0.985738}, {2.68123, -0.180248, -0.110539}, {4.68779, 0.22483,
0.0725717}, {5.41664, 0.982811, 0.491087}, {6.43321, 0.624075,
0.167138}, {6.60217, 1.59568, 2.19137}, {5.48321, -0.612703,
1.54037}, {0.275933, 1.73027, -0.319963}, {1.16899,
2.62176, -0.426422}, {0.895252, 2.30479, 0.546692}, {1.32435,
1.46099, -0.247962}, {2.438, 1.54727, -1.84394}, {2.84289, 2.47839,
0.487663}, {0.947902, 2.01877, 1.65962}, {4.27311, 1.66672,
1.82603}, {3.51098, 1.72636, 0.209131}, {2.53455, 2.68654,
1.45134}, {3.79154, 1.91726, 3.06622}, {5.59738, 1.69974,
1.26923}, {4.74771, 2.06686, 0.627377}, {5.8998, 1.90073,
0.269334}, {3.76603, 2.71011, 0.018981}, {6.52431, 1.09702,
1.0249}, {0.514549, 4.44605, -0.926816}, {1.18538,
3.8988, -0.291136}, {-1.03715, 3.48421, -0.126283}, {2.15475,
3.24303, -0.291715}, {1.96754, 2.39311, 0.152853}, {2.28468,
4.21156, 0.0596945}, {1.41851, 4.21297, 1.93538}, {1.77912, 3.13171,
0.827817}, {3.40729, 3.67042, -0.335001}, {4.14912, 4.26701,
0.858455}, {3.42495, 3.43054, 0.832514}, {2.65226, 0.773315,
1.84478}, {4.50074, 3.62477, -0.228838}, {5.67743,
4.08899, -1.0032}, {4.98032, 2.56005, 1.60549}, {5.21301,
2.61515, -0.189593}, {-0.716714, 4.48811, -0.0695819}, {0.924003,
5.67242, 0.689366}, {1.02188, 6.33087, 1.77669}, {0.330792, 4.2462,
0.228187}, {1.79568, 5.98731, -0.447117}, {1.4538,
4.91975, -0.371939}, {1.49597, 5.34725, 1.68155}, {1.49152, 4.62994,
0.659604}, {4.00242, 4.6745, -0.284203}, {3.10622, 4.50629,
0.728059}, {3.87473, 5.84693, 1.31431}, {2.98275, 5.88126,
0.697273}, {4.87938, 4.86575, 0.0826803}, {6.47473, 5.84112,
1.05569}, {4.76077, 5.92404, 0.606916}, {6.4309, 3.70755,
0.813097}, {0.104133, 0.851572, 3.46545}, {0.551016, 0.780983,
1.69373}, {-0.594108, 2.62214, 1.8779}, {0.708406, -0.797156,
2.9291}, {2.0969, -0.257719, 1.69345}, {3.93626, -0.163324,
0.657445}, {0.781078, 1.36067, 2.66083}, {3.8494, 0.656096,
1.86343}, {4.30525, -0.0180448, 2.46287}, {4.80984, 0.218372,
1.24748}, {2.76467, -0.0677178, 2.53374}, {4.58791, -0.856503,
3.05766}, {5.59133, -0.108523, 0.470608}, {7.29888, 0.209516,
2.63152}, {5.34566, 0.991826, 4.06735}, {4.31354, 0.951664,
2.75418}, {0.786024, 0.835163, 0.374784}, {1.49562, 0.756177,
2.29413}, {-1.31348, 3.36, 2.05473}, {1.96944, 1.82599,
2.15945}, {1.75072, 1.30223, 1.27227}, {2.25839, 3.48229,
2.18914}, {0.348436, 2.50653, 2.4213}, {1.82846, 1.37269,
3.04588}, {3.31408, 2.12509, 2.05064}, {3.41257, 3.28132,
2.45043}, {2.73336, 1.98305, 2.98785}, {5.36672, 1.01905,
2.02999}, {4.49376, 3.19686, 0.674299}, {5.6424, 2.95267,
0.927283}, {4.58006, 2.97117, 2.42488}, {5.10568, 1.9436,
2.47794}, {0.0359706, 2.12641, 1.14963}, {0.136018,
3.47913, -0.546182}, {0.324015, 3.19016, 1.53741}, {-0.364055,
3.30565, 2.57457}, {0.639834, 3.29517, 0.505645}, {2.21284, 3.99436,
1.14992}, {1.21456, 3.05581, 2.09513}, {2.94578, 3.94601,
3.25965}, {3.09293, 3.99949, 1.79511}, {4.15348, 3.53126,
1.64667}, {3.17003, 4.95903, 2.7816}, {3.98937, 3.99651,
2.56071}, {4.79954, 4.84892, 3.01249}, {5.35644, 4.06114,
0.728884}, {6.14876, 5.29657, 1.8754}, {3.95394, 2.44156,
1.21713}, {0.00856939, 6.32042, 1.89394}, {-0.435331, 7.36044,
2.55351}, {0.19939, 5.0767, 3.33505}, {-0.347543, 4.13423,
1.7466}, {0.481867, 4.5129, 1.26472}, {2.29653, 4.50625,
2.36835}, {0.351039, 5.00868, 2.20155}, {1.53178, 3.70154,
2.98418}, {2.53732, 5.04177, 1.5255}, {3.72857, 4.78197,
1.72687}, {3.20208, 5.71681, 2.0526}, {5.32521, 6.78749,
2.3629}, {5.22618, 5.09716, 1.11705}, {5.94678, 7.11508,
1.51961}, {4.62847, 5.63837, 1.95489}, {6.28939, 4.82977,
0.848559}, {0.0461207, 1.93522, 3.25444}, {0.371978, -0.0986856,
3.58917}, {-0.461638, 1.25587, 4.47311}, {0.584499, -0.644038,
4.46688}, {2.48808, -0.420693, 3.44016}, {2.41666, 0.660956,
3.88881}, {1.55183, -0.235559, 2.81671}, {1.59083, -0.113905,
4.47863}, {3.60737, 0.284417, 3.38969}, {4.14487, 1.05219,
3.87699}, {4.27162, 0.351588, 4.8352}, {4.79354, 0.125734,
3.38844}, {5.27955, 0.079976, 4.41649}, {5.41948, 0.854351,
3.03103}, {5.22856, 0.775168, 5.21907}, {6.37806, 0.167375,
4.72112}, {-1.02014, 1.96112, 3.69853}, {-0.419047, 2.83171,
3.46298}, {-1.31457, 2.99279, 4.20992}, {2.44419, 0.358023,
4.95077}, {1.49318, 2.32455, 3.03509}, {0.432945, 4.0273,
3.6404}, {2.43741, 2.95397, 3.21087}, {3.14394, 1.4998,
3.86404}, {3.25509, 0.897897, 2.71971}, {4.45936, 3.20951,
3.55269}, {3.9792, 2.36403, 4.23043}, {4.70902, 1.5701,
4.75358}, {4.67827, 2.15833, 3.48814}, {5.44659, 2.80719,
3.058}, {5.12916, 3.09863, 5.67653}, {7.26935, 1.50287,
4.25862}, {-1.81989, 4.53932, 1.82345}, {0.556698, 3.93986,
2.51026}, {0.995211, 4.14387, 4.78229}, {0.27128, 3.07496,
4.3641}, {-0.718274, 3.82941, 3.61474}, {1.34653, 3.4258,
4.05185}, {0.666971, 2.94969, 3.26312}, {3.41411, 2.84055,
3.56064}, {2.67536, 5.2721, 3.64452}, {3.40383, 5.93004,
3.15271}, {4.1124, 6.19419, 3.95084}, {4.08112, 4.5837,
4.80518}, {4.98851, 3.90126, 2.90884}, {6.04449, 4.53769,
2.73099}, {5.45906, 5.56679, 2.58463}, {5.09465, 4.17775,
3.97109}, {-0.175458, 4.9133, 4.37999}, {0.880872, 5.07276,
4.35447}, {-0.131287, 5.91199, 5.42513}, {1.58653, 4.74081,
3.71834}, {1.36079, 5.03015, 2.71108}, {2.43226, 5.70154,
4.58147}, {1.42105, 5.88282, 3.64901}, {2.1028, 4.374,
4.68369}, {2.18209, 5.72639, 2.59178}, {5.44592, 6.0964,
3.55996}, {3.63535, 6.13173, 5.09292}, {4.66946, 5.20011,
4.01056}, {6.4787, 6.02617, 2.89552}, {6.054, 6.96222,
3.57906}, {6.46182, 5.96925, 3.94092}, {5.69617, 5.10088,
3.64138}, {0.615022, -0.027696, 5.42941}, {1.26461, 0.630006,
3.71384}, {0.883915, 1.42777, 5.47437}, {1.6792, 0.219376,
5.6289}, {2.59437, -0.684772, 5.60909}, {3.38078, 0.833026,
5.01004}, {2.84052, 0.573809, 5.90501}, {2.52553, 0.273467,
7.55756}, {4.41898, 0.696667, 5.85818}, {5.60858, 0.76452,
6.21228}, {5.74785, -1.1999, 7.01252}, {5.21135, -0.1117,
5.70978}, {4.66543, -0.919731, 4.87041}, {5.88829, 2.25357,
4.8022}, {6.3881, 1.00455, 5.545}, {6.22542, 0.0248028,
6.01928}, {0.586144, 0.520938, 4.41165}, {1.2068, 2.54395,
4.71756}, {0.436429, 2.33501, 5.52469}, {1.97207, 1.17024,
5.77531}, {2.25879, 3.04413, 5.01964}, {3.16137, 2.32338,
5.14988}, {2.02769, 2.28359, 5.84169}, {2.83295, 1.61539,
5.95777}, {3.8353, 1.69209, 5.8488}, {3.96829, 4.30873,
3.70322}, {2.99406, 2.69444, 6.18322}, {4.51472, 1.36171,
6.60083}, {3.63584, 3.42738, 4.39589}, {6.12614, 2.20446,
5.82261}, {4.02039, 2.78657, 5.66757}, {5.06004, 1.83423,
5.81263}, {1.10964, 3.21626, 5.41782}, {0.855608, 5.48462,
5.49}, {-0.571077, 3.27243, 5.29777}, {2.72265, 4.45985,
5.80695}, {1.48765, 1.09592, 4.7271}, {2.57181, 3.58383,
4.09092}, {1.85261, 3.99701, 5.63123}, {2.39584, 2.38821,
4.08817}, {3.14111, 4.4719, 4.37108}, {3.24159, 5.19853,
5.18419}, {2.9781, 5.51286, 6.43951}, {3.5866, 3.85079,
5.36787}, {4.57368, 3.59342, 4.68331}, {5.97774, 4.05604,
4.6439}, {4.63198, 4.10956, 5.6602}, {6.58299, 2.72811,
6.98548}, {-0.360483, 4.87033, 5.40138}, {1.66172, 6.00282,
5.1889}, {0.0873425, 5.97487, 6.85352}, {-0.0873903, 5.21734,
6.30516}, {2.00121, 5.14253, 5.51722}, {4.29976, 5.27308,
5.64666}, {0.988506, 6.73676, 6.59325}, {2.25374, 5.26316,
7.00213}, {3.74567, 6.67823, 6.34782}, {4.79574, 5.92614,
6.35025}, {3.28421, 6.66997, 4.2437}, {3.88385, 5.62567,
6.89584}, {3.46529, 5.45601, 4.13669}, {5.23652, 4.7538,
4.97666}, {5.72676, 5.96949, 4.96138}, {5.58535, 5.25335, 5.92877}}


coord contains the {x, y, z} coordinates of 256 particles.

Distance[x_, y_, z_] :=  If[# < z/2, #, Sequence @@ {}] & @
Sqrt[Total[((x - y) - z*Round[(x - y)/z])^2]]


Distance computes the periodic distance between two particles and only returns it if it meets a criterion.

• What do you consider "more elegant"? Feb 8, 2013 at 23:53
• @jVincent, anything better than Table Feb 8, 2013 at 23:55
• Why use ParallelTable? Try Compile with Table or Do loop and approriate options. The only way to be even faster is to use C or Fortran for the loop and use MathLink. Fortran rules. Feb 9, 2013 at 0:06
• This question is a nice addition to the discussion here: Alternatives to procedural loops and iterating over lists in Mathematica
– Jens
Feb 9, 2013 at 6:15
• Related: (8272) Feb 9, 2013 at 7:28

mutualDistances[coords_,distF_] :=
distF @@@ Subsets[coords, {2}]


?

In your case, you should use distf = Distance[##,z]& with whatever your z is. The result you get corresponds to what you'd get with your Table code, if you additionally Flatten it.

• @jVincent Yes, that's true. I have a habit of working with indices,but here they don't bring much of an advantage. Will edit your suggestion in, thanks. Feb 9, 2013 at 0:27
• This is clearly an elegant way. I'm just waiting to see other clever solutions before I accept it. Thanks for your input, I learned something new today. Feb 9, 2013 at 0:38
• @RunnyKine Right, it is a good habit to not accept immediately. This would motivate others to contribute more answers. Feb 9, 2013 at 0:39

In cases like this, you could also use SparseArray. The equivalent of your Table command would be:

dist = SparseArray[{i_, j_} :> Distance[coord[[i]], coord[[j]], 3] /; i > j, 256];


where Distance and coord are as defined in your question, and 3 is some arbitrary value I chose for z.

You can get all the non-zero values as

dist["NonzeroValues"]


and you'll have Null wherever Distance returned a Sequence[]. You can remove this by either defining your sequence to return 0 (in which case, you can simply use dist["NonzeroPositions"] to get the pairs for which something was returned), or via a replacement: /. Null -> Sequence[]

• Another elegant solution. Thanks. Feb 9, 2013 at 0:47

I suppose subsets is what you're looking for. Similar to Leonid's answer:

Select[EuclideanDistance @@@ Subsets[coords, {2}], # < z/2 &]


Another function along these lines is Outer, which operates on the Cartesian product of two lists. (Tuples and Permutations are also useful).