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$

5 Answers 5

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

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

$\endgroup$
3
  • $\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, 2018 at 19:40
  • $\begingroup$ @andre Now that you say it, I cannot recall that I have used this ever successfully... $\endgroup$ Oct 5, 2018 at 19:46
  • 2
    $\begingroup$ This new syntax is documented (in version 11.3) $\endgroup$
    – andre314
    Oct 5, 2018 at 19:49
15
$\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$
3
  • 2
    $\begingroup$ lst[[All, 1]] = Sqrt@lst[[All, 1]]; is probably the most efficient method for it uses vectorization. $\endgroup$ Oct 5, 2018 at 22:46
  • 2
    $\begingroup$ @HenrikSchumacher, Transpose[... Transpose] seems to be faster for real numbers. $\endgroup$
    – kglr
    Oct 6, 2018 at 11:35
  • $\begingroup$ also lst // {Sqrt@#[[All, 1]], #[[All, 2]]} & // Transpose $\endgroup$
    – user1066
    Oct 6, 2018 at 18:18
12
$\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$
1
  • $\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$ Oct 6, 2018 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.