15
$\begingroup$

Consider the function f which should behave as

f[{{1, 2}, {3, 4}, {5, 6, 7}}]
{f[{1, 2}], f[{3, 4}], f[{5, 6, 7}]}

The following code doesn't worked as expectation

fromDig[ls_?VectorQ] := 10^Range[Length@ls - 1, 0, -1].ls;
SetAttributes[fromDig, Listable];
fromDig@{{1, 2}, {3, 4}, {5, 6}}

I figured out a way, using Compile,

Clear["Global`*"];
cfromDig = Compile[{{A, _Integer, 1}},
 10^Range[Length@A - 1, 0, -1].A, RuntimeAttributes -> {Listable}];
cfromDig[{{1, 2}, {3, 4}, {5, 6}}]

Is there a better way?

$\endgroup$
  • $\begingroup$ I am not sure if I understand, but why not just: fromDig2[ls_List] := 10^Range[Length@# - 1, 0, -1].# & /@ ls; fromDig2@{{1, 2}, {3, 4}, {5, 6}}? (or FromDigits /@ {{1, 2}, {3, 4}, {5, 6}}:) ) $\endgroup$ – Pinguin Dirk Sep 26 '13 at 5:59
  • $\begingroup$ ...or fromDig3[ls__] := 10^Range[Length@{ls} - 1, 0, -1].{ls}; fromDig3 @@@ {{1, 2}, {3, 4}, {5, 6}} $\endgroup$ – gpap Sep 27 '13 at 10:47
16
$\begingroup$

I'm pretty sure this is a duplicate but I spent 15 minutes looking for it and couldn't find it, so I'm just going to answer for now.

Instead of using Listable you can manually map over non-vector lists:

f[v_?VectorQ] := oper[v]
f[ls_List] := f /@ ls;

f[{{1, 2}, {3, 4}, {5, 6, 7}}]
{oper[{1, 2}], oper[{3, 4}], oper[{5, 6, 7}]}

Extension

In an attempt to make this answer more unique, consider the advanced behavior of Listable functions wherein non-list arguments are distributed:

SetAttributes[ff, Listable]
ff["x", {1, 2, 3}, {4, 5, 6}]
{ff["x", 1, 4], ff["x", 2, 5], ff["x", 3, 6]}

We may wish to have this behavior extended, in a fashion at least, to our "vector atoms" as used above. The simplest method I can think of is to use Thread, which has the same behavior as Listable though only at level one, and guard the vectors form recognition and threading. Here an unoptimized first pass at implementation:

g[a___] /; MemberQ[{a}, x_List /; ! VectorQ[x]] :=
  Module[{h},
    g @@@ Replace[Thread@Replace[Hold[a], v_?VectorQ :> h[v], {1}], h@x_ :> x, {2}]
  ]

Now:

g[1, {2, 3}, {{{4}}, {5, 6}, 7}]
{{g[1, {2, 3}, {4}]}, g[1, {2, 3}, {5, 6}], g[1, {2, 3}, 7]}

Note that the vector {2, 3} is distributed as 1 is, while the nested lists are threaded. When {4} is encountered it is also treated as atomic, but its surrounding List is transferred to the output: {g[1, {2, 3}, {4}]}.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.