# How do I operate on this list elegantly? [duplicate]

This question already has an answer here:

calibData = { {200, 10}, {100, 20} }

MapAt[N, MapAt[Log10, calibData, {;; , 1}], {;; , 1}]


I want to apply a base 10 Log to the first element of each tuple. Then the output should be displayed as a floating point number.

This bit of code does the job, but it is ugly and its hard to understand what it is doing. Is there a better way of completing this task?

## marked as duplicate by Artes, halirutan♦, Michael E2, m_goldberg, rm -rf♦Oct 9 '13 at 2:44

• This is using the solution of that post. I think this was a new issue I had. The motivation behind the post was to understand functional style programming to a greater extent. – olliepower Oct 8 '13 at 22:52
• Have no idea why this post got downvoted... – Leo Fang Oct 9 '13 at 0:28

If you have a large amount of calibData, then preserving packed arrays can greatly improve speed. Convert it all to Reals and then apply logarithm.

calibData = 10 RandomInteger[{1, 20}, {10^6, 2}];

Transpose @ {Log10 @ #[[1]], #[[2]]} &@ Transpose @ N @ calibData; // AbsoluteTiming
(* {0.098568, Null} *)

Transpose @ {Log10 @ N @ calibData[[All, 1]], N @ calibData[[All, 2]]}; // AbsoluteTiming
(* {0.106482, Null} *)

MapAt[Log10, N@calibData, {All, 1}]; // AbsoluteTiming
(* {1.525485, Null} *)


The second components of calibData get converted to Real in this process. If you need them to be integers, you might use Round if the integers are not too large. Otherwise, you can hope that the performance with unpacked arrays is acceptable.

Compared with unpacked:

Transpose @ {Log10 @ N @ calibData[[All, 1]], calibData[[All, 2]]}; // AbsoluteTiming
(* {0.369981, Null} *)

MapAt[N @ Log10[#] &, calibData, {All, 1}]; // AbsoluteTiming
(* {8.740113, Null} *)


The arrays will be unpacked in these cases because the numbers are not all the same type (some Real, some Integer).

This question has probably been asked here before, or something similar. I can't find it yet but try this:

MapAt[N@Log10[#] &, calibData, {All, 1}]


OR via pattern-matching:

calibData /. {x_, y_} :> {N@Log10[x], y}


Using Apply:

{N @ Log10 @ #1, #2} & @@@ calibData