Monday, March 28, 2011

Replace 2 strings at the same time?

hello

how can I replace 2 strings in the same time? for example let's say I have string like this:

str1 = "AAAA BBBB CCCC DDDD"

i want to replace every "AAAA" with "CCCC" and every "CCCC" with "AAAA" but if i did:

str1.gsub("AAAA","CCCC") # CCCC BBBB CCCC DDDD

str1.gsub("CCCC","AAAA") # AAAA BBBB AAAA DDDD

what I want str1 to be "CCCC BBBB AAAA DDDD"

From stackoverflow
  • General answer:
    Use a regex to match both AAAA and CCCC, then substitute each match with CCCC and AAAA respectively.

    edit to clear up the confusion

    str1.gsub(/(AAAA|CCCC)/) { $1 == 'AAAA' ? 'CCCC' : 'AAAA' }
    

    edit i thought of a more elegant way too :)

    str1.gsub(/((AAAA)|(CCCC))/) { $2 ? 'CCCC' : 'AAAA' }
    
    Barry Fandango : Agree, that feels like a much better solution than the other suggestions. I can't figure out what the regex would be though.
    Morendil : Just use the alternation operator: AAAA|CCCC
    Barry Fandango : Agreed Morendil, but what would the replace syntax look like? You'll need to put your finds into groups like: (AAAA)|(CCCC) And then do some kind of trickiness in the replace with \1 and \2.
    some : javascript: "AAAA BBBB CCCC DDDD".replace(/AAAA|CCCC/g,function(a){ return a==="AAAA" ? "CCCC" : "AAAA";});
    Marcus Downing : My previous negative comment has been deleted, now I see what you mean.
    bobince : As SO's resident anti-regex-overuse whinger, I endorse this approach :-)
  • Is it an option for you to replace AAAA with something else first and then proceed?

    str1.gsub("AAAA","WXYZ") # WXYZ BBBB CCCC DDDD
    str1.gsub("CCCC","AAAA") # WXYZ BBBB AAAA DDDD
    str1.gsub("WXYZ","CCCC") # CCCC BBBB AAAA DDDD
    
    alexandrul : Just take care at choosing the temporary string to replace AAAA with, it should not exist in the original string.
    Calyth : Don't know why the -1 was there... Technically, regular expression (as a language) has no memory. i.e. the accept solution above shouldn't work. Alexandrul already pointed out the pitfall. regular expression as a tool can do what the accepted solution does...
  • A solution (although something based around regex would be best) would be something along the lines of creating a replacement hash as such, which can be extended as needed. I just quickly put this together to demonstrate. I'm sure with a bit more love and care you can come up with something more elegant that works along the same lines as this implementation only works for strings with spaces.

    str1 = "AAAA BBBB CCCC DDDD"    
    replacements = { "AAAA" => "CCCC", "CCCC" => "AAAA", "XXXX" => "ZZZZ" } # etc...
    
    new_string = ""
    str1.split(" ").each do |s| 
        new_string += replacements[s] || s
        new_string += " "
    end
    
    puts new_string # CCCC BBBB AAAA DDDD
    

0 comments:

Post a Comment