10
$\begingroup$

If I have a list for example :

  {{4,1},{9,2},{16,3},{25,4}}

Is there a command that replaces the first element by its square root and returns a list ? In the example above it would return :

  {{2,1},{3,2},{4,3},{5,4}}

(Obviously the list above is short and easy to manipulate, but I'm asking a question for a longer and more complicated one)

$\endgroup$
21
$\begingroup$
MapAt[Sqrt, {{4, 1}, {9, 2}, {16, 3}, {25, 4}}, {All, 1}]

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

$\endgroup$
  • $\begingroup$ Very interesting. I have tested version 8 (it doesn't work) and version 11.3 (it works). I think that this capability was introduced with version 10 because the documentation of MapAt mentions an update at version 10. By the way, Mathematica accepts the following syntax too : MapAt[Sqrt, {{4, 1}, {9, 2}, {16, 3}, {25, 4}}, {2;;-2, 1}] . $\endgroup$ – andre314 Oct 5 '18 at 19:40
  • $\begingroup$ @andre Now that you say it, I cannot recall that I have used this ever successfully... $\endgroup$ – Henrik Schumacher Oct 5 '18 at 19:46
  • 1
    $\begingroup$ This new syntax is documented (in version 11.3) $\endgroup$ – andre314 Oct 5 '18 at 19:49
14
$\begingroup$
lst = {{4, 1}, {9, 2}, {16, 3}, {25, 4}};
lst[[All, 1]] = Sqrt@lst[[All, 1]];
lst

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

Also

lst = {{4, 1}, {9, 2}, {16, 3}, {25, 4}};
Transpose[{Sqrt[#[[1]]], #[[2]]}&@Transpose[#]]&@lst

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

And

lst = {{4, 1}, {9, 2}, {16, 3}, {25, 4}};
lst = ReplacePart[lst, {a_, 1} :> Sqrt[lst[[a, 1]]]]

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

$\endgroup$
  • 2
    $\begingroup$ lst[[All, 1]] = Sqrt@lst[[All, 1]]; is probably the most efficient method for it uses vectorization. $\endgroup$ – Henrik Schumacher Oct 5 '18 at 22:46
  • 2
    $\begingroup$ @HenrikSchumacher, Transpose[... Transpose] seems to be faster for real numbers. $\endgroup$ – kglr Oct 6 '18 at 11:35
  • $\begingroup$ also lst // {Sqrt@#[[All, 1]], #[[All, 2]]} & // Transpose $\endgroup$ – user1066 Oct 6 '18 at 18:18
11
$\begingroup$
{Sqrt[#1], #2} & @@@ {{4, 1}, {9, 2}, {16, 3}, {25, 4}}

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

And much to my astonishment, using Part with Map is faster than the above (0.015 seconds vs 0.060 seconds on list of length 100,000)

{Sqrt[#[[1]]], #[[2]]} & /@ {{4, 1}, {9, 2}, {16, 3}, {25, 4}}

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

Or, if you felt compelled to use patterns,

{{4, 1}, {9, 2}, {16, 3}, {25, 4}} /. {a_?NumericQ, b_} :> {Sqrt[a], b}

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

or

Cases[{{4, 1}, {9, 2}, {16, 3}, {25, 4}}, {a_?NumericQ, b_} :> {Sqrt[a], b}]

{{2, 1}, {3, 2}, {4, 3}, {5, 4}}

$\endgroup$
  • $\begingroup$ @user202729 Thank you. I have fixed the pattern replacement methods to account for two element lists. Though the fix is assuming the first element is always numeric, which of course works in this case, but not in general. $\endgroup$ – That Gravity Guy Oct 6 '18 at 17:06
6
$\begingroup$

I like to use Replace whenever possible:

Replace[
  {{4, 1}, {9, 2}, {16, 3}, {25, 4}},
  {first_, rest__} :> {Sqrt[first], rest},
  {1}
 ]
(* {{2, 1}, {3, 2}, {4, 3}, {5, 4}} *)
$\endgroup$
2
$\begingroup$

or Map a user defined function down the list:

f[{x_, y_}] := {Sqrt[x], y}
f /@ {{4, 1}, {9, 2}, {16, 3}, {25, 4}}
(* {{2, 1}, {3, 2}, {4, 3}, {5, 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.