1

I'm looking for a function that approximates the functionality Ruby's gsub or javascript replace. So you could do something like

   replace("Too many horses are horses","horses", "dogs")

and end up with "Too many dogs are dogs"

Any ideas?

3

1 Answer 1

-1

Couldn't find a library so had to write it. This seems to work although verbose and probably expensive. (replaceString ends up depending on a lot of other functions like getSlice, findInString the code for which included below. In turn those functions depend on some basic string functions like .concat like .length at .charAt which are pretty basic, so not shown but available in other string libraries.

function replaceString( string memory source, 
                        string memory stringToFind, 
                        string memory replacementString
                       ) 
                        public  view returns(string memory) {
    int startPos = findInString(source, stringToFind, 0);
    if (startPos == -1) return source;
    uint start =  uint(startPos);
    string memory beforeString;
    string memory afterString;
 
    if (start <= 1) {
        beforeString = "";
    } else {
        beforeString = getSlice(source, 1, start-1);
    }
    uint end = uint(beforeString.length() + stringToFind.length());
   
    if (end>= uint(source.length())) {
        afterString = "";
    } else {
        afterString = getSlice(source, end +1, uint(source.length())-end);
    }
    string memory retval = beforeString.concat(replacementString); 
    if(afterString.length()>0) {
       retval = retval.concat(afterString);
    }         
    return retval;
}

 function getSlice(string memory source, uint startPos, uint numChars) public pure returns (string memory) {
       uint ustartPos = uint(startPos -1);
       uint _numChars = uint(numChars);

        bytes memory sourcebytes = bytes(source);
       if (_numChars==0) {
           _numChars = ((sourcebytes.length - ustartPos) + 1);
       }
      
      bytes memory result = new bytes(_numChars);     

      for (uint i = 0; i<_numChars; i++) {
          result[i] = sourcebytes[i + ustartPos];
      }
      return string(result); 
    }

function findInString(string memory source, string memory findString, uint startAfter ) public  pure returns(int) {
        uint targetLength = findString.length();
        uint sourceLength = source.length();
         
        require(targetLength > 0 || sourceLength > 0, "missing param source or findingString");
        require (startAfter <= (sourceLength - targetLength) + 1, "startAfter is larger than source - findstring"); 
         
     
        //look for first occurrence of first character in in target in source
           //if not found 
           //    exit -1;
            //else if found, check the following character to see if it is the second character in target and continue
            //  until end of target is encountered or there is a mismatch.
            //if there is a mismatch, check for the second occurrence of the first character in target in source and repeat
         uint sourceIndex = startAfter + 1;
         uint targetIndex = 1;
         //character we are looking for now:
         string memory firstChar = charAt(findString, 1);
         
         while(sourceIndex <= (sourceLength - targetLength)) {
             //need an int so we can figure out if it's -1;
             
             int index = findChar(source, firstChar, sourceIndex -1);
             if (index == -1) {return -1;}  //first character of search term not found in source
             if (targetLength == 1) {return index;}  //Search for a single character.
             sourceIndex = uint(index);
             //we found the first character.  Look for the rest of the string;
             uint nextSourceIndex = sourceIndex + 1;
             targetIndex = 2;
             while(targetIndex <= targetLength) {
                 
                 string memory charToFind=charAt(findString, targetIndex);
                 string memory nextSourceChar = charAt(source, nextSourceIndex);
          
                 if (!(charToFind.compareTo(nextSourceChar))){
                
                     break;
                 }
                 if(targetIndex == targetLength) {
                     return int(sourceIndex);
                 } else {
                    nextSourceIndex += 1;
                    targetIndex++;
                 }
             }
             sourceIndex +=1;   
         }
         return -1;
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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