问题
I'm looking for an efficient way to replace the values within an object if they match a certain pattern.
var shapes = {
square: {
attr: {
stroke: '###',
'stroke-width': '%%%'
}
},
circle: {
attr: {
fill: '###',
'stroke-width': '%%%'
}
}
}
For instance, i'd like to be able to replace all '###' patterns with a colour for a specific shape:
var square = replace(shapes.square, {
'###': '#333',
'%%%': 23
});
var circle = replace(shapes.circle, {
'###': '#111',
'%%%': 5
});
Which would allow me quickly to set the stroke and/or fill values of various objects.
Is there a way to do this cleanly? Perhaps using Lodash or regex?
回答1:
In lodash, you have a utility function mapValues
function replaceStringsInObject(obj, findStr, replaceStr) {
return _.mapValues(obj, function(value){
if(_.isString(value)){
return value.replace(RegEx(findStr, 'gi'), replaceStr);
} else if(_.isObject(value)){
return replaceStringInObject(value, findStr, replaceStr);
} else {
return value;
}
});
}
回答2:
Plain JS, no library needed:
var shapes = {
square: {
attr: {
stroke: '###',
'stroke-width': '%%%'
}
},
circle: {
attr: {
fill: '###',
'stroke-width': '%%%'
}
}
}
shapes = JSON.parse(
JSON.stringify(shapes).replace(/###/g,"red").replace(/%%%/g,"23")
)
console.log(shapes);
回答3:
The JavaScript String.prototype.replace() API should allow you to do exactly that!
You'd have to walk the properties of the object first, but that should be pretty trivial.
回答4:
Elaborating on meir answer (getting rid of lodash dependency and circular processing):
function replaceStringsInObject(obj, findStr, replaceStr, cache = new Map()) {
if (cache && cache.has(obj)) return cache.get(obj);
const result = {};
cache && cache.set(obj, result);
for (let [key, value] of Object.entries(obj)) {
let v = null;
if(typeof value === 'string'){
v = value.replace(RegExp(findStr, 'gi'), replaceStr);
}
else if (Array.isArray(value)) {
v = value;
for (var i = 0; i < value.length; i++) {
v[i] = replaceStringsInObject(value, findStr, replaceStr, cache);
}
}
else if(typeof value === 'object'){
v = replaceStringsInObject(value, findStr, replaceStr, cache);
}
else {
v = value;
}
result[key] = v;
}
return result;
}
回答5:
You can use _.transform in order to substitute the value of the attribute by the one passed in the object of replacements. In case of the value not being in the replacements, the original value is used.
function replace(src, repl) {
return {
attr: _.transform(src.attr, function(result, val, key) {
result[key] = repl[val] || val;
}, {})
};
}
var shapes = {
square: {
attr: {
stroke: '###',
'stroke-width': '%%%'
}
},
circle: {
attr: {
fill: '###',
'stroke-width': '%%%'
}
}
};
var square = replace(shapes.square, {
'###': '#333',
'%%%': 23
});
var circle = replace(shapes.circle, {
'###': '#111',
'%%%': 5
});
console.log(square);
console.log(circle);
<script src="https://cdn.jsdelivr.net/lodash/4.16.6/lodash.min.js"></script>
来源:https://stackoverflow.com/questions/40380084/js-replacing-all-string-values-in-an-object-that-match-a-pattern