Message Boards Message Boards

1
|
7435 Views
|
3 Replies
|
5 Total Likes
View groups...
Share
Share this post:

Anything like list comprehensions in the Wolfram Language ?

Posted 9 years ago

Do we have an easy way, without having recourse to join or flatten, of generating flat lists in the Wolfram Programming Language, akin to the list comprehension construct available in other functional programming languages ?

For example in Clojure, we can generate a flat list of tuples like so :

user=> ( for [ i ( range 3 ) j ( range i ) ] [ i j ] )
([1 0] [2 0] [2 1])

Of, if we so wish, a nested list, like so :

user=> ( for [ i ( range 3 ) ] ( for [ j ( range i ) ] [ i j ] ) )
(() ([1 0]) ([2 0] [2 1]))

Whereas in the Wolfram Programming Language it seems to me we are forced to generate nested lists and flatten them afterwards, like so :

Join@@Table[{i,j},{i,Range[3]},{j,Range[i]}]

In case there is no builtin support for such constructs, I suppose with some neat metaprogramming trick one may easily come up with a solution, though...

Thanks for your help.

POSTED BY: Fabien Todescato
3 Replies
Posted 9 years ago

You can create a table with an one-dimensional index:

Table[k, {k, Subsets[Range[0, 2], {2}]}]

If you want to feed the resulting indices to a function:

Table[Apply[f, k], {k, Subsets[Range[0, 2], {2}]}]

Achieving the resulting indices in the same order as you have given is a bit more tricky:

Reverse[Table[Apply[f, k], {k, Subsets[Range[2, 0, -1], {2}]}]]
POSTED BY: Michael Helmle

Note that Subsets is just the very special case you describe above, for any general dependence of i and j this approach won't be easier, as the argument supplied to Table then needs to come from somewhere ;) But good to point out that Table can 'iterate' over any list as well. (Do, Sum and others can also do this).

POSTED BY: Sander Huisman

Generally: NO, Mathematica will always give back nested lists of any dimensions you like. If you really want flattened lists, there are multiple options: Either using Join and or Flatten as you mentioned, another solutions is to use Sow and Reap:

Reap[Do[Sow[{i,j}],{i,Range[3]},{j,Range[i]}]][[2,1]]

But I'm quite sure this will be slower in most cases. For the 'rectangular' cases (i.e. the output would have been a N-Dimensional rectangle) you can also get a 1D list if you do it in one of these ways:

Flatten[Table[{i,j},{i,5},{j,8}],1]
Join@@Table[{i,j},{i,5},{j,8}]
Reap[Do[Sow[{i,j}],{i,5},{j,8}]][[2,1]]
Tuples[{Range[5],Range[8]}]

You can't however use Tuples for those 'ragged' cases, like the example you gave.

Perhaps easiest is the following:

FlatTable[a_, x__] := Flatten[Table[a, x], Length[{x}] - 1]

which will create 'your table' that flattens it for you.

POSTED BY: Sander Huisman
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract