Forum Moderators: open

Message Too Old, No Replies

Using object value as a replacement in .replace()

         

csdude55

7:51 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



How can I use $1 to replace the matched text with the object value?

This is my test script:

var str = 'John';

var chars = {
'John' : 'Jack'
};

// I want to replace "John" with "Jack
str = str.replace(/(\w+)/, chars['$1']);


This returns 'undefined', with no errors in the console.

I've tried every variation I can think of (including chars[$1], chars[RegExp.$1], and , function(v) { return chars[v]; }) but everything I've tried either returns '' or 'undefined'.

If I do this:

var str = 'John is ';
str = str.replace(/(\w+)\s\w+/, '$1');


then it returns 'John", so I know that $1 is definitely matching the ( ) as expected. And this:

str = str.replace(/(\w+)\s\w+/, chars['John']);


returns 'Jack' as expected, so it's not an issue of not being able to use the object name here. The issue appears to be getting it to recognize that $1 is 'John' in chars[$1].

NickMNS

8:00 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



What exactly is $1? I think you're confusing PHP and JS

If you want to use the var str as the key to your object then simply do:
chars[str]

csdude55

8:10 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Working on that for 2 days, and as soon as I post I come up with a near solution! LOL

str = str.replace(/(\w+)/g,
function(v, match) {
if (chars[match])
return chars[match];
else return v;
}
);


So a backup question:

Is there a better way to "do nothing" if chars[match] doesn't exist, rather than returning v back to it?

csdude55

8:11 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



@NickMNS, I was using this as a guide:

[developer.mozilla.org...]

NickMNS

9:45 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Is there a better way to "do nothing" if chars[match] doesn't exist, rather than returning v back to it?

str = str.replace(/(\w+)/g, chars[match] || null );

NickMNS

9:48 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Actually I'm not sure this will accomplish what you want. It will return "null" if it doesn't match, but in the str.replace it will replace the value with null.

NickMNS

10:04 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I read the Mozilla link.
To answer you first questions:

let str = "John is"
str.match(/(\w+)/);
const matched = RegExp.$1
str = str.replace(matched, chars[matched])
console.log(str) // "Jack is"

csdude55

10:23 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That last is better than using the function() in mine, when chars[matched] doesn't exist there's no issue :-) Thanks, Nick!

Fotiman

10:31 pm on Nov 8, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Your regex, /(w+)/g, is definitely going to match your string, meaning you will ALWAYS be replacing some value with another. If you instead want to only replace the value if you have a value to replace it with, then you'll need a conditional check of some kind. I would use a ternary, like this:

var str = 'John is';
var chars = {
'John': 'Jack'
};
var regexp = /(\w+)/;
var input = 'John'; // Note, this could be a param of a function
var match = chars[input];
str = match === undefined ? str : str.replace(regexp, match);

NickMNS

12:37 am on Nov 9, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ok! Now let's clean all up and combine.

@Fotiman, good point. The last line can be "beautified", variables are truthy and "undefined" resolves as false, so you can just use the variable name directly "match" instead "match === 'undefined'", but you need invert the str and str.replace.

Sorry, guys I'm sticking with ES6 syntax it's time to move on.

let str = "John is"
str.match(/(\w+)/);
const matched = RegExp.$1
str = matched ? str.replace(matched, chars[matched]) : str

Fotiman

1:44 am on Nov 9, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I deliberately tested for undefined in case there is a case for replacing with an empty string.

csdude55

6:39 pm on Nov 9, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm pretty sure the answer is "no", but is there a reason to NOT do:

if (chars[matched] !== undefined)
str = str.replace(matched, chars[matched])

Fotiman

7:46 pm on Nov 9, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That is roughly equivalent to what I had, with the difference being that my example is more terse and keeps it all on one line. My example always performs the assignment (which is trivial), so it's not technically equivalent to your example above (you'd need an else condition). Also, I'd probably change my code slightly to this:

str = match !== undefined ? str.replace(regexp, match) : str;

Fotiman

8:06 pm on Nov 9, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



A couple more thoughts on the thread above. I would probably avoid the RegExp.$1 syntax because it's less well known (and RegExp is complicated enough already). Anyone maintaining this could may need to go researching to find out what that is and how it works. Instead, I'd try to make this as clear as possible.

Given an input string and a target string, replace instances of the input string in the target string with values defined in a map, and return the modified target string or the original target string if the input string is not defined in the map.


const person = 'John';
const template = 'John is here';
const map = {
John: 'Jack'
};

function replaceWithMapValue(input, target, map) {
const regexp = /(\w+)/;
const value = map[input];
const result = value !== undefined ? target.replace(regexp, value) : target;
return result;
}

console.log(replaceWithMapValue(person, template, map));

NickMNS

9:17 pm on Nov 9, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



@Fotiman I don't think you fully understand the goal.
$1 or more specifically RegExp.$1 was used to capture the first word of the phrase and to use that word as the input of the look-up table.

Also since the input is RegExp.$1 and the expression \w+ captures words so there is no case for an empty string. Finally, if the case were to exist and a replacement should occur then a value would need to be set for map[""]. With a value set the lookup of map[""] would return a value and "value" would no longer be "false".

Fotiman

3:41 pm on Nov 10, 2021 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



@NickMNS, oh, you're right, I did misunderstand the goal to capture the first word of the phrase. That changes everything. :) In that case, ignore my comments about not using RegExp.$1.