How to repeat the nonblank string?
In place modification of a list works well here:
fc[list_] := Module[{out=list},
With[{empty = Pick[Range[2,Length@list], Rest@list,""]},
out[[empty]]=out[[empty-1]]
];
out
]
A comparison with Mr Wizard's fn:
data = RandomChoice[{"","","","a","b"}, 10^5];
r1 = fn[data]; //AbsoluteTiming
r2 = fc[data]; //AbsoluteTiming
r1 === r2
{0.049858,Null}
{0.01092,Null}
True
As I presently interpret the question
(Now with refinements after considering Chris Degnen's simultaneous answer)
fn[list_] :=
Partition[list, 2, 1, -1, ""] // Cases[{p_, ""} | {_, p_} :> p]
Test:
{"", "x", "y", "", "z", ""} // fn
{"", "x", "y", "y", "z", "z"}
Patterns
Since you seem only to be interested in a pattern-matching solution here is my proposal to avoid the extremely slow use of ReplaceRepeated
while still using pattern-matching as the core of the operation.
fn2[list_] :=
list // ReplacePart @
ReplaceList[list, {a___, p_, "", ___} :> (2 + Length@{a} -> p)]
Recursive replacement
I just realized that this is a perfect time to use a self-referential replacement:
fn3[list_] :=
list /. {a___, p_, "", b___} :> {a, p, p, ##& @@ fn3@{b}}
Benchmark
All three methods are much faster than kglr's foo
(note the log-log scale).
Now with Carl Woll's fc
, the fastest method yet. ( but no patterns ;-) )
Needs["GeneralUtilities`"]
$RecursionLimit = 1*^5;
BenchmarkPlot[{foo, fn, fn2, fn3, fc},
RandomChoice[{"", "", "", "a", "b"}, #] &
]
Update:
foo = # //. {a___, p : Except["", _String], Longest[b : "" ..], c___} :>
{a, p, p, ## & @@ ConstantArray["☺", Length[{b}] - 1], c} /. "☺" -> "" &;
{"", "", "", "3$71", "", "", "2$72", "", "", "", ""} // foo
{"", "", "", "3$71", "3$71", "", "2$72", "2$72", "", "", ""}
Previous post:
rule = {a___, p : Except["", _String], Longest["" ..], b___} :> {a, p, p, b};
{"", "", "", "3$71", "", "", "2$72", "", "", "", ""} //. rule
{"", "", "", "3$71", "3$71", "2$72", "2$72"}