Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a bunch of arrays looking like this:

{"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 300.348, 293.108, 285.86, 278.599, 271.39...

What is a good way of filling out the blanks with the next number? That is to assume that blanks simply mean the sequence of values is being constant. There may be blanks in between two numbers as well, not just at the beginning as in the sample above.

share|improve this question

5 Answers 5

up vote 7 down vote accepted

You could do something like this

list = Append[RandomReal[5, 30] /. a_ /; a < 2 :> "", 1.]
{3.82088, "", 2.17919, 2.38081, "", "", 4.54655, "", "", 3.97074, "",
 3.72551, 4.75268, "", "", "", "", "", "", "", "", 2.74955, "", "",
 4.98933, 2.40911, 3.72805, "", 4.50331, 4.75458, 1.}
Reverse[FoldList[#2 /. {"" -> #1} &, Last[list], Reverse[Most[list]]]]
{3.82088, 2.17919, 2.17919, 2.38081, 4.54655, 4.54655, 4.54655,
 3.97074, 3.97074, 3.97074, 3.72551, 3.72551, 4.75268, 2.74955,
 2.74955, 2.74955, 2.74955, 2.74955, 2.74955, 2.74955, 2.74955,
 2.74955, 4.98933, 4.98933, 4.98933, 2.40911, 3.72805, 4.50331,
 4.50331, 4.75458, 1.}
share|improve this answer

Here is a straightforward linear-time version

Flatten@Map[Replace[#, _ -> Last@#, {1}] &, Split[list, ! NumericQ@# &]]
share|improve this answer
    
This solution has a problem when the last element of the list is blank. I commented under your solution, but the comment holds also for the solutions by Heike, Szabolcs and Artes. –  VLC Mar 14 '12 at 16:52
3  
@vucko Yes, I am aware of that. But, if you think about it, in such case the problem is not well-formulated anyway, because it is not clear what should be the substitution. So, the best one can do within the given formulation is to include argument checks to filter out such cases, but I did not bother. –  Leonid Shifrin Mar 14 '12 at 16:55
    
@vucko I didn't forget about that, but you didn't indicate what you want to do with that situation, so I assumed it can't happen. There are several possibilities. Can you explain (in the question) what you want to do with that last blank? –  Szabolcs Mar 14 '12 at 18:43
    
@Szabolcs I don't have any specific request. I just wanted to leave here a note about something that wasn't directly mentioned in the answers. –  VLC Mar 14 '12 at 19:53

Lazy people's slow but simple solution:

data //. {s___, "", next_?NumericQ, e___} :> {s, next, next, e}
share|improve this answer
list = {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
        "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 
        "", "", "", "", "", "", "", 300.348, 293.108, 285.86, 278.599, 271.39};

Yet another way :

list //. {x___, PatternSequence["", c_?NumericQ], y___} -> {x, c, c, y}
share|improve this answer

Here is a variation of Leonid's method that is somewhat faster:

Join @@ Map[Last@# ~ConstantArray~ Length@# &, Split[list, ! NumericQ@# &]]

Timings:

list = Append[RandomReal[5, 300000] /. a_ /; a < 2 :> "", 1.];

Flatten@Map[Replace[#, _ -> Last@#, {1}] &, 
    Split[list, ! NumericQ@# &]]; // AbsoluteTiming

Join @@ Map[Last@# ~ConstantArray~ Length@# &, 
    Split[list, ! NumericQ@# &]]; // AbsoluteTiming
{0.4180239, Null}

{0.3080176, Null}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.