# Inserting a 0 in Specific Symbols

I have a very large network with 1000's of edges. Below is a small sample. The N is my label for Node and the number that follows is a unique identifier. I want to make all the edges on either side of the arrow (->) into a string of 6 characters. If the left side of the arrow has just 5 characters, then I want to all insert a 0 to the right of the N. Likewise, if the right side of the arrow has just 5 characters, then I want to all insert a 0 to the right of the N. If both sides of the arrow already have 6 characters then do nothing to that edge. The set edges2 is the outcome I'm trying to reach from starting with edges1. Any assistance is much appreciated!

edges1 = {N1003 -> N1003, N1003 -> N1099, N1003 -> N12059,
N1003 -> N22007, N1003 -> N1025}
edges2 = {N01003 -> N01003, N01003 -> N01099, N01003 -> N12059,
N01003 -> N22007, N01003 -> N01025}

• edges1 /. x_Symbol /; StringTake[tmp = ToString[x], 1] == "N" && StringLength[tmp] == 5 :> "N0" <> StringTake[tmp, {2, 5}] Commented Aug 4 at 7:27
• {N01025->N01025,N01025->N01025,N01025->N12059,N01025->N22007,N01025->N01025} Commented Aug 4 at 12:11
• hmmm...seems to not produce edges2 but some other edge set using N01025 in all the pairs. Commented Aug 4 at 12:13
• Sorry, should read: edges1 /. x_Symbol /; (StringTake[ToString[x], 1] == "N" && StringLength[ToString[x]] == 5) :> "N0" <> StringTake[ToString[x], {2, 5}] Commented Aug 4 at 18:08
• nice!!!!!!!!!!!!!!!!!!!! Commented Aug 4 at 18:16

((edges1 /. Rule[a_,b_] :> Rule[ToString[a],ToString[b]]) /.
(str_String /; StringLength[str]==5) :>
StringJoin@Insert[StringTakeDrop[str,1],"0",2])/.
str_String :> Symbol[str]

(* {N01003->N01003,N01003->N01099,N01003->N12059,N01003->N22007,N01003->N01025} *)

% === edges2

(* True *)

• A. Kato: This is a neat solution and very clever ... many thanks for all your help ... regards ... 42700 Commented Aug 4 at 4:34

You say "string" but all of your N1003-like things are symbols. So, I'll cover both cases. We start with a helper method that works on a single string/symbol

StringPadAt2[s_String] := StringInsert[s, "0", 2] /; 5 == StringLength[s];
StringPadAt2[s_Symbol] := Symbol[StringInsert[SymbolName[s], "0", 2]] /; 5 == StringLength[SymbolName[s]];


So, if we have strings and we want strings:

edges1Strings = {"N1003" -> "N1003", "N1003" -> "N1099", "N1003" -> "N12059", "N1003" -> "N22007", "N1003" -> "N1025"};
(* {"N01003" -> "N01003", "N01003" -> "N01099", "N01003" -> "N12059", "N01003" -> "N22007", "N01003" -> "N01025"} *)


Alternately, you could use ReplaceAll:

edges1Strings /. {s_String :> StringPadAt2[s]}


If we have symbols and we want symbols:

edges1Symbols = {N1003 -> N1003, N1003 -> N1099, N1003 -> N12059, N1003 -> N22007, N1003 -> N1025};
(* {N01003 -> N01003, N01003 -> N01099, N01003 -> N12059, N01003 -> N22007, N01003 -> N01025} *)


And again with ReplaceAll:

edges1Symbols /. {s_Symbol :> StringPadAt2[s]}


This can be adjusted to do string->symbol or symbol->string. As it stands, I'm assuming that we always start with strings/symbols that are 5 or 6 characters long. If you have other cases, this would need to be generalized.

• lericr: thank you for that clarification on symbol vs string; wonderful code and thank u for sharing this! Commented Aug 4 at 4:31
edges1 = {N1003 -> N1003, N1003 -> N1099, N1003 -> N12059,
N1003 -> N22007, N1003 -> N1025};

edges2 = {N01003 -> N01003, N01003 -> N01099, N01003 -> N12059,
N01003 -> N22007, N01003 -> N01025};


Using StringReplace:

f[str_String] /; StringLength@ToString@str != 5 := str

f[str_String] /; StringLength@ToString@str == 5 :=
StringReplace[str, # -> # <> "0"] &@StringTake[str, 1]

(edges1 /.
Rule[a_, b_] :> Map[Symbol@*f]@(Rule @@ (ToString /@ {a, b}))) === edges2


True

Or using StringReplacePart:

f[s_Symbol] :=
With[{ss = ToString@s},
If[StringLength@ss == 5,
Symbol[StringReplacePart[#, StringTake[#, 1] <> "0", {1, 1}] &@ss], s]]

Map[f, edges1, {-1}] === edges2


True

• clever with StringReplace ... nice idea!! ... thank u! Commented Aug 5 at 10:47