There are a lot of ways to do this, but here is one:
Method1[list_] := Fold[
Function@ReplacePart[#1, #2 -> ("string" <> ToString[#1[[#2]]])],
list,
Range[1, Length[list], 3]];
Method1 @ Range[9]
{"string1", 2, 3, "string4", 5, 6, "string7", 8, 9}
For help understanding this, see the Fold function, and the ReplacePart function. This is a rather functional way of solving the problem; a more procedural method might look like this:
Method2[listArg_] := Module[
{list = listArg},
Do[
list[[i]] = "string" <> ToString[list[[i]]],
{i, 1, Length[list], 3}];
list];
Method2 @ Range[9]
{"string1", 2, 3, "string4", 5, 6, "string7", 8, 9}
You can also set the list directly, if list is not a function argument or a constant:
Method3[listArg_] := Module[
{list = listArg},
list[[1 ;; All ;; 3]] = ("string" <> ToString[#]) & /@ list[[1 ;; All ;; 3]];
list];
Method3 @ Range[9]
{"string1", 2, 3, "string4", 5, 6, "string7", 8, 9}
And, one final way:
Method4[list_] := MapAt[
Function["string" <> ToString[#]],
list,
List /@ Range[1, Length[list], 3]];
Method4 @ Range[9]
{"string1", 2, 3, "string4", 5, 6, "string7", 8, 9}
Edit:
As pointed out by Rorschach, some of these methods are slow for large lists (specifically, methods 1, 2, and 4 are fairly slow). For completeness, I've placed Rorschach's method just below. The Method3 above runs faster in my own tests than Rorschach's proposed method (due, probably, to the partitioning in Rorschach's method), while methods 1 and 4 can be rearranged slightly to run in comparable time; a new method 1 is below, and method 4 can be adapted to look like the solution given by Kuba.
RorschachsMethod[list_] := Flatten@Map[
{"string" <> ToString[#[[1]]], #[[2]], #[[3]]} &,
Partition[r, 3]];
KubaMethod[list_] := MapAt[
Function["string" <> ToString[#]],
list,
{1 ;; All ;; 3}];
NewMethod1[list_] := With[
{range = Range[1, Length[list], 3]},
ReplacePart[
list,
Thread[range -> (("string" <> ToString[#]) & /@ list[[range]])]]];
In case speed is an issue for anyone, and for the sake of completeness, the fastest version of this function I was able to come up with (without employing any parallel or compiling tools) is below:
FastMethod[listArg_] := Module[
{list = listArg},
list[[1 ;; All ;; 3]] = MapThread[
StringJoin,
{ConstantArray["string", Floor[(Length[list] + 2)/3]],
ToString /@ list[[1 ;; All ;; 3]]}];
list];
This last method runs slightly faster than the original Method3 and in about half the time (for argument Range[10^6]) of any other method I've seen:
With[
{r = Range[10^6]},
Table[
fn -> First@AbsoluteTiming[fn[r]],
{fn, {Method3, NewMethod1, RorschachMethod, KubaMethod, FastMethod}}]]
{Method3 -> 1.42383,
NewMethod1 -> 2.59458,
RorschachMethod -> 2.90768,
KubaMethod -> 1.42317,
FastMethod -> 1.26555}