7
$\begingroup$

I have a list of strings and I would check if there is an empty string element, that's "", because I need to replace it with a "0". I try the following

StringReplace[{"90", "", "20"}, "" -> "0"]

and I get the following (unexpected) answer:

(* {"09000", "0", "02000"} *)

I think it is quite strange, not sure if it's a wrong or designed behavior. Any sensible explanation? It could be related to this other strange result:

StringPosition[{"90", "", "20"}, ""]

{{{1, 0}, {2, 1}, {3, 2}}, {{1, 0}}, {{1, 0}, {2, 1}, {3, 2}}}

I don't need a solution, because the alternative to my original issue is easy, but I'm posting here just to have other opinions.

$\endgroup$
8
$\begingroup$

As others have indicated this result is not surprising at all. What you actually need is not StringReplace but ReplaceAll (/.):

{"90", "", "20"} /. "" -> "0"

{"90", "0", "20"}

| improve this answer | |
$\endgroup$
  • $\begingroup$ That's right! I was working with strings for other issues so my brain was focused on strings but actually here I do not need to check something "inside" a string, rather to check the whole object and ReplaceAll does the work. Thanks $\endgroup$ – bobknight Mar 20 '15 at 15:20
7
$\begingroup$

The illustrated behavior seems reasonable to me, even if it may not seem "natural."

  1. For position or replacement a given pattern should match when it appears between any two sequences of characters, or it is at the beginning and end of a string. A zero-length string effectively is between every pair of characters. Why should it not match? To keep it from matching would seem to call for an exception. What other behavior would it have?

  2. If a null string did not behave as shown how would you achieve this behavior? I believe you would need another token such as WordBoundary. It is shorter and equally logical for "" to be used instead.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Yes, you are right. Taking a deeper look at the results and thanks to your explanation, now I can understand that the answers from both functions are correct and they do exactly what you well explained. Thanks for that explanation. $\endgroup$ – bobknight Mar 20 '15 at 15:29
5
$\begingroup$

That is a rather slippery replacement, "Find nothing and replace it with something" Try telling the replacement that there nothing between the beginning and end

StringReplace[{"90", "", "20"}, {StartOfString ~~ "" ~~ EndOfString -> "0"}]
| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ You don't even need "", nor braces: StringReplace[{"90", "", "20"}, StartOfString ~~ EndOfString -> "0"] $\endgroup$ – enzotib Mar 20 '15 at 11:29
  • $\begingroup$ As I commented above, in my actual case the most appropriate solution is ReplaceAll, however your solution with StartOfString/EndOfString is valid as well, in particular when one have to work inside strings with zero-length string. Thanks for that solution. $\endgroup$ – bobknight Mar 20 '15 at 15:27
1
$\begingroup$

StringReplace just searched from left to right and replaced all the zero-length string for once. Here is a way to visualize the process:

i = 0; StringReplace[{"90", "", "20"}, 
 "" :> ToString[Style["0", {Orange, 15 + 5 i++}], StandardForm]]

enter image description here

The inserted zero is dyed into orange and becomes bigger every time the replacing rule is applied so you can see where and how the replacement happens.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Yes, that's an example of what Mr.Wizard explained by words. Thanks for the answer. $\endgroup$ – bobknight Mar 21 '15 at 9:05

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.