A straightforward translation of a general list comprehension, suggested by various Python tutorials, even if not the most efficient way (see for instance @Roman's answer), is to append each item to a list:
Module[{res = {}},
MapIndexed[ (* use Do[], Map[], or MapIndexed[] to implement the iterable *)
Function[{array, i},
MapIndexed[
Function[{el, j},
If[i != j, (* if condition *)
AppendTo[res, {el, First@i, First@j}]] (* add to list *)
],
array
]
],
matrix
];
res
]
Reap
and Sow
might be the closest thing in Mathematica to a list comprehension, and effectively implements the above approach.
Reap[
MapIndexed[
Function[{array, i},
MapIndexed[
Function[{el, j},
If[i != j, Sow[{el, First@i, First@j}]]
],
array
]
],
matrix
]
][[2, 1]]
And Reap
-Sow
allows multiple list comprehensions simultaneously with the second tag argument.
Note: Sometimes one can use Table[]
with If[condition, x, Nothing]
to implement [x for x in list if condition]
. But implementing nested iterations with Table[]
, such as in the OP's example, would result in nested lists instead of a flat list. They could be flattened. For the OP's example:
Flatten[
Table[
With[{array = matrix[[i]]},
Table[
With[{el = array[[j]]},
If[i != j, {el, i, j}, Nothing]
],
{j, Length@array}
]
],
{i, Length@matrix}
],
1
]
Note that with Table[]
, Do[]
, and Map[]
you can only have one item, either the index j
or the element el
. If you get the index, you can extract the element as above.. To get both at once, you would have to use MapIndexed
. Note also that instead of Table[]
, you can use MapIndexed
at level 2, as in @Roman's answer, which produces a nested, non-flat, result. Using MapIndexed[]
instead of Table[]
above gives us the following solution:
Flatten[
MapIndexed[
If[Unequal @@ #2, Flatten[{##}], Nothing] &,
matrix,
{2}],
1]
Dataset
. $\endgroup$MapIndexed
is tofor (i, array) in enumerate(matrix)
. And since you have to use a nested loop in python, how do you expect not to have to use a loop in M? $\endgroup$MapIndexed
with a level spec of{2}
and a conditionalNothing
and then callFlatten[#, 1]
on that? Seems to me to be the easiest way. $\endgroup$