4
$\begingroup$

This is a question about ReplacePart but if there's a better that's great.

If I have a list

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

and I want to replace elements 1,3,5 with elements a,b,c from list {a,b,c}, can I use ReplaceParts to do this in one step?

I have only been able to do this replacing one element at a time.

Thanks.

$\endgroup$
  • 1
    $\begingroup$ list /. {1 -> a, 3 -> b, 5 -> c} $\endgroup$ – Hubble07 Dec 31 '14 at 9:18
  • $\begingroup$ @Hubble07: You are saying that if the first list contains 1000 elements and the second list contains 500 that I would have to type 1->a, etc. 500 times? $\endgroup$ – daniel Dec 31 '14 at 9:45
  • $\begingroup$ Isn't there some way to use a list of indices and replacement elements and do this all at once? $\endgroup$ – daniel Dec 31 '14 at 9:54
  • 4
    $\begingroup$ you have names conflict, a is a list and an element of the last list. p.s. does this work for you: list /. Thread[{1,2,3}->{a,b,c}]? $\endgroup$ – Kuba Dec 31 '14 at 9:57
  • 1
    $\begingroup$ for this specific case you can use a[[;; ;; 2]]= {aa,b,c}. I have changed a to aa because of name conflict as kuba mentioned. $\endgroup$ – Algohi Dec 31 '14 at 10:09
6
$\begingroup$

I would suggest not using ReplacePart but Part assignment or Riffle instead.

Three functions to compare:

repOdd1[old_, new_] := ReplacePart[old, Thread[Range[1, Length@old, 2] -> new]]

repOdd2[old_, new_] := Module[{x = old}, x[[;; ;; 2]] = new; x]

repOdd3[old_, new_] := Riffle[new, old[[2 ;; ;; 2]]]

Test:

a = Range@9;
b = {q, r, s, t, u};

repOdd1[a, b]
repOdd2[a, b]
repOdd3[a, b]
{q, 2, r, 4, s, 6, t, 8, u}

{q, 2, r, 4, s, 6, t, 8, u}

{q, 2, r, 4, s, 6, t, 8, u}

Performance:

a = Range@999999;
b = Range[1000001, 1500000];

repOdd1[a, b] // AbsoluteTiming // First
repOdd2[a, b] // AbsoluteTiming // First
repOdd3[a, b] // AbsoluteTiming // First
1.052060

0.002000

0.008001

Both Part and Riffle are orders of magnitude faster than ReplacePart. Part assignment is a bit more verbose than Riffle if we include Module but also faster and applicable for in-place modification should that be desired.

Part also works for an arbitrary index list, not only an evenly spaced Span:

(* in-place modification in this example *)

a = Range@9;
b = {q, r, s, t, u};
a[[{1, 2, 9, 7, 5}]] = b;
a
{q, r, 3, 4, u, 6, t, 8, s}

I am a fan of using Part for many operations: Elegant operations on matrix rows and columns

$\endgroup$
  • $\begingroup$ Kuba has not posted his/her answer--what do you think of that suggestion, out of curiosity? $\endgroup$ – daniel Dec 31 '14 at 11:09
  • $\begingroup$ @daniel By my interpretation of the question that is not a solution. I am assuming that the list elements 1, 2, 3, are arbitrary, not always natural numbers 1..n. $\endgroup$ – Mr.Wizard Dec 31 '14 at 11:11
  • $\begingroup$ With that in mind I will accept yours as the more general solution, although because my lists are almost always of numbers Kuba's response was helpful. $\endgroup$ – daniel Dec 31 '14 at 11:16
  • 1
    $\begingroup$ @daniel If you wish to replace by index it will be faster to do that using Part assignment. However if you wish to replace elements by pattern, which is what Kuba's code does, it is not applicable. These are two different operations with only one intersection: the case where the starting list is Range[ n ]. $\endgroup$ – Mr.Wizard Dec 31 '14 at 11:20
8
$\begingroup$

What about

ReplacePart[{1, 2, 3, 4, 5}, Thread[{1, 3, 5} -> {a, b, c}]]

or in general

replaceParts[original_, positions_, replacements_] := ReplacePart[
    original,
    Thread[positions -> replacements]
]
$\endgroup$
  • $\begingroup$ Assuming it works, doesn't add a step? Basically in Kuba's note it's just "Thread." Very economical. But if it works, fine.+1 $\endgroup$ – daniel Dec 31 '14 at 10:44
  • 1
    $\begingroup$ No. There are two steps in both my example is: ReplacePart[{1, 2, 3, 4, 5}, Thread[{1, 3, 5} -> {a, b, c}]], while Kuba's is ReplaceAll[{1, 2, 3, 4, 5}, Thread[{1, 3, 5} -> {a, b, c}]]. Secondly Kuba's only works if the original list is a Range, mine works with any list. $\endgroup$ – Carlo Dec 31 '14 at 16:32
  • $\begingroup$ Inner[Rule,{1,3,5},{a,b,c}] should be faster than Thread[{1, 3, 5} -> {a, b, c}], if speed is a consideration. $\endgroup$ – Soldalma Sep 28 '16 at 21:00
4
$\begingroup$

I prefer other answers (particularly Part if the application permits it), but I will take this opportunity to mention the undocumented four-argument form of ReplacePart:

ReplacePart[{1, 2, 3, 4, 5}, {a, b, c}, {{1}, {3}, {5}} , {{1}, {2}, {3}}]
(* {a,2,b,4,c} *)

This syntax says to replace parts 1, 3, and 5 of {1, 2, 3, 4, 5} with parts 1, 2, and 3 of {a, b, c}. This syntax has been supported for a very long time, but it is undocumented so I suppose it could disappear some day.

Incidentally, and not relevant to the present question, there is also an undocumented three-argument form:

ReplacePart[{1, 2, 3, 4, 5}, {a, b, c}, {{1}, {3}, {5}}]
(* {{a,b,c},2,{a,b,c},4,{a,b,c}} *)

This form says to replace parts 1, 3, and 5 of {1, 2, 3, 4, 5} with the value {a, b, c}.

$\endgroup$
  • $\begingroup$ I almost posted this myself but I could not see how it simplified the problem so I did not. You were probably the one I learned it from. Is this posted elsewhere on site? $\endgroup$ – Mr.Wizard Dec 31 '14 at 23:57
  • $\begingroup$ @Mr.Wizard I posted here because it is vaguely relevant and I haven't seen it mentioned elsewhere on the site. There are more posts that use ReplacePart than I care to review, so it might be out there somewhere. I'm pretty sure I've discussed it before somewhere in the StackExchange universe, but it would have been in chat or a comment. $\endgroup$ – WReach Jan 1 '15 at 0:46
  • $\begingroup$ One reference: (17344). Anyway +1 for taking the time to remind us of this nugget even it if doesn't fit perfectly. $\endgroup$ – Mr.Wizard Jan 1 '15 at 6:04
2
$\begingroup$
ReplacePart[{1, 2, 3, 4, 5}, {i_?OddQ} :> {a, b, c}[[(i + 1)/2]]]

{a, 2, b, 4, c}

$\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.