lambdaway
::
replace
1
|
list
|
login
|
load
|
|
_h1 selectively replace multiple instances{br}of a character within a string _p The task given in [[rosettacode|http://rosettacode.org/wiki/Selectively_replace_multiple_instances_of_a_character_within_a_string]]: {prewrap Given the string: "abracadabra", replace programatically: the first 'a' with 'A' the second 'a' with 'B' the fourth 'a' with 'C' the fifth 'a' with 'D' the first 'b' with 'E' the second 'r' with 'F' The answer should, of course, be : "AErBcadCbFD". } _h2 1) first answer _p We first translate the replacements program into a sequence of rules {pre the first 'a' with 'A' -> aA1 the second 'a' with 'B' -> aB2 the fourth 'a' with 'C' -> aC4 the fifth 'a' with 'D' -> aD5 the first 'b' with 'E' -> bE1 the second 'r' with 'F' -> rF2 } _p Then we add to the existing set of array functions a new one finding the indexes of some value in a given array. {prewrap '{def A.findindexes {def A.findindexes.rec {lambda {:v :a :b :i} {if {A.empty? :a} then :b else {A.findindexes.rec :v {A.rest :a} {if {W.equal? {A.first :a} :v} then {A.addlast! :i :b} else :b} {+ :i 1}} }}} {lambda {:v :a} {A.findindexes.rec :v :a {A.new} 0} }} -> {def A.findindexes {def A.findindexes.rec {lambda {:v :a :b :i} {if {A.empty? :a} then :b else {A.findindexes.rec :v {A.rest :a} {if {W.equal? {A.first :a} :v} then {A.addlast! :i :b} else :b} {+ :i 1}} }}} {lambda {:v :a} {A.findindexes.rec :v :a {A.new} 0} }} '{A.findindexes a {A.split abracadabra}} -> {A.findindexes a {A.split abracadabra}} '{A.findindexes b {A.split abracadabra}} -> {A.findindexes b {A.split abracadabra}} '{A.findindexes r {A.split abracadabra}} -> {A.findindexes r {A.split abracadabra}} } _p Using {b findindexes} we can translate the {b aA1 aB2 aC4 aD5 bE1 rF2} sequence into a new one where numbers are replaced by indexes in the given string, here {b abracadabra}. {pre '{def replacements.rules {lambda {:w :r} {A.new {W.get 0 :r} {W.get 1 :r} {A.get {- {W.get 2 :r} 1} // arrays begin at 0 {A.findindexes {W.get 0 :r} {A.split :w}}}}}} -> {def replacements.rules {lambda {:w :r} {A.new {W.get 0 :r} {W.get 1 :r} {A.get {- {W.get 2 :r} 1} {A.findindexes {W.get 0 :r} {A.split :w}}}}}} '{A.join {replacements.rules abracadabra aA1}} -> {A.join {replacements.rules abracadabra aA1}} '{A.join {replacements.rules abracadabra aB2}} -> {A.join {replacements.rules abracadabra aB2}} ... '{A.join {replacements.rules abracadabra rF2}} -> {A.join {replacements.rules abracadabra rF2}} } _p Finally the {b replacements} function will apply this sequence of rules to the word. {pre '{def replacements {def replacements.rec {lambda {:word :rules} {if {A.empty? :rules} then {A.join :word} else {replacements.rec {A.set! {A.get 2 {A.first :rules}} {A.get 1 {A.first :rules}} :word} {A.rest :rules}} }}} {lambda {:word :rules} {replacements.rec {A.split :word} {A.map {replacements.rules :word} {A.new :rules}} }}} -> {def replacements {def replacements.rec {lambda {:word :rules} {if {A.empty? :rules} then {A.join :word} else {replacements.rec {A.set! {A.get 2 {A.first :rules}} {A.get 1 {A.first :rules}} :word} {A.rest :rules}} }}} {lambda {:word :rules} {replacements.rec {A.split :word} {A.map {replacements.rules :word} {A.new :rules}} }}} } _p Testing {pre '{replacements abracadabra aA1 aB2 aC4 aD5 bE1 rF2} -> {replacements abracadabra aA1 aB2 aC4 aD5 bE1 rF2} (AErBcadCbFD) '{replacements caaarrbabad aA1 aB2 aC4 aD5 bE1 rF2} -> {replacements caaarrbabad aA1 aB2 aC4 aD5 bE1 rF2} (cABarFECbDd) } _h2 2) second answer using regexps _p Here is a quick, "homemade" answer using the {b S.replace_once} primitive. {pre '{def multrepl_rex {lambda {:word :rules} {if {A.empty? :rules} then :word else {multrepl_rex {S.replace_once {W.first {A.first :rules}} by {W.last {A.first :rules}} in :word } {A.rest :rules}} }}} -> {def multrepl_rex {lambda {:word :rules} {if {A.empty? :rules} then :word else {multrepl_rex {S.replace_once {W.first {A.first :rules}} by {W.last {A.first :rules}} in :word } {A.rest :rules}} }}} '{multrepl_rex abracadabra {A.new aA aB a3 aC aD 3a // save third "a" as "3" and restore it bE // first "b" r1 rF 1r // save first "a" as "1" and restore it }} -> {multrepl_rex abracadabra {A.new aA aB a3 aC aD 3a bE r1 rF 1r }} (AErBcadCbFD) } _p {i alain marty 2022/06/11} {script LAMBDATALK.DICT['S.replace_once'] = function () { // {replace_once one by two in some text} var str = LAMBDATALK.supertrim(arguments[0]); // one by two in text var index = str.indexOf('by'); var one = str.substring(0,index).trim(); str = str.substring(index+2).trim(); index = str.indexOf('in'); var two = str.substring(0,index).trim().replace(/€/g,'$'); two = (two !== 'space')? two : ' '; str = str.substring(index+2).trim(); str = str.replace( RegExp(one,''), two ); return str; }; }
lambdaway v.20211111