开发者

Functional mapping on a list of points

I have a list of points:

points = {{0.144, 1.20}, {0.110, 1.60}, {0.083, 2.00}, {0.070, 2.40},
         {0.060, 2.80}, {0.053, 3.20}, {0.050, 3.60}, {0.043, 4.00}}

I want to p开发者_如何学编程ass each point to this function, returning a new point:

coordinate[length_,frequence_] = {(1/(2*length)) , (frequence*1000)}

Which should result in a list like so:

 { {3.47, 12 000}, {4.54, 16 000}, ... }

I've been trying to do so with map:

 data = Map[coordinate, points]

It yields something like:

 {coordinate[{0.144, 1.2}], coordinate[{0.11, 1.6}]}

At first that seems correct, except it passes a list rather than just arguments. However, even if I change my coordinate function to accept a list (by changing the expected parameter to list_ and changing length to list[[1]] and frequence to list[[2]]), I won't be able to use the list returned by that map for e.g. linear regression by LinearModelFit[data, x, x]["BestFit"].


The simplest way that uses your definition, is Apply at level 1 which has the shorthand @@@. (See the more info part of the Apply documentation.) So, you want

points = {{0.144, 1.20}, {0.110, 1.60}, {0.083, 2.00}, {0.070, 
   2.40}, {0.060, 2.80}, {0.053, 3.20}, {0.050, 3.60}, {0.043, 4.00}}

coordinate[length_, frequence_] := {(1/(2*length)), (frequence*1000)}

coordinate @@@ points

Note that I've changed your definition into a SetDelayed instead of just Set (pay attention to the syntax highlighting showing you the localized variables on the right hand side). See the Immediate and Delayed Definitions guide page.

This said, it's probably best to make coordinate take a list instead of a sequence, as done in belisarius' and ninjagecko's answers, i.e.,

coordinate[{length_, frequence_}] := {(1/(2*length)), (frequence*1000)}


coordinate[{length_, frequence_}] := {(1/(2*length)), (frequence*1000)}
data = coordinate /@ points
(*
->{{3.47222, 1200.}, {4.54545, 1600.}, {...
*)

And

lm = LinearModelFit[data, x, x]
(*
-> -40.3573 + 348.678 x
*)

Show[ListPlot[data], Plot[lm[x], {x, 0, 15}], Frame -> True]

Functional mapping on a list of points


Change your definition to

coordinate[point_] := {(1/(2*point[[1]])) , (point[[2]]*1000)}


coordinate[{length_, frequence_}] := {1/(2*length), frequence*1000}
coordinate /@ points

sidenote: I would personally stay away from the @@@ that has been proposed in other answers, since it feels awkward to me as a programmer. But those answers are also certainly valid.


Alternatively, you could use Apply instead of Map:

coordinate @@@ points

output:

{{3.47222, 1200.}, {4.54545, 1600.}, {6.0241, 2000.}, {7.14286, 2400.}, 
 {8.33333, 2800.}, {9.43396, 3200.}, {10., 3600.}, {11.6279, 4000.}}


I feel that @@@ is the cleanest way to handle this. However, if you can to redefine coordinate but you do not want remove its existing syntax, you may consider this construct.

Clear[coordinate]
coordinate[length_, frequence_] := {(2 length)^-1, 1000 frequence}
coordinate[l_List] := Apply[coordinate, l, {-2}]

The new line adds a definition to handle lists. This assumes that your arguments are not themselves objects with depth. It allows for quite a bit of flexibility in the way you use the function:

coordinate[0.144, 1.20]

(*Out= {3.47222, 1200.} *)

coordinate[{0.144, 1.20}]

(*Out= {3.47222, 1200.} *)

coordinate[points]

(*Out= {{3.47222, 1200.}, {4.54545, 1600.}, {6.0241, 
  2000.}, {7.14286, 2400.}, {8.33333, 2800.}, {9.43396, 3200.}, {10., 
  3600.}, {11.6279, 4000.}} *)

coordinate /@ points

(*Out= {{3.47222, 1200.}, {4.54545, 1600.}, {6.0241, 
  2000.}, {7.14286, 2400.}, {8.33333, 2800.}, {9.43396, 3200.}, {10., 
  3600.}, {11.6279, 4000.}} *)

coordinate @@@ points

(*Out= {{3.47222, 1200.}, {4.54545, 1600.}, {6.0241, 
  2000.}, {7.14286, 2400.}, {8.33333, 2800.}, {9.43396, 3200.}, {10., 
  3600.}, {11.6279, 4000.}} *)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜