-
Notifications
You must be signed in to change notification settings - Fork 1.4k
convert html entities
S1ngS1ng edited this page Apr 10, 2017
·
1 revision
- 这个
function
接收一个字符串参数str
。返回值为转换后的字符串 - 如果传入的字符串是
"Dolce & Gabbana"
,那么返回值应为"Dolce & Gabbana"
- 在这道题目中,只有以下五个字符需要转换:
-
&
需转换为'&'
-
<
需转换为'<'
-
>
需转换为'>'
-
'
需转换为'''
-
"
需转换为'"'
-
- 这道题目难度不大,基本解法中我们先用最简单的遍历去解决。当然,首先需要生成一个空字符串用于存储结果
- 类似的思路是,可以先
split
,然后操作数组,最后再join
。由于思路很相似,这里就不给出了 - 需要注意的是遍历的开始位置,这很重要。可以先考虑一下,如果从左边开始遍历,由于替换的字符串比原字符长,因此字符串总长度会增加。换句话说,增加的字符串会占用未遍历到的位置
- 因此,从右边开始遍历会是一个更好的选择。另外,从右边开始遍历的话,初始值要设置为
str.length - 1
。跳出条件也应该是i < 0
。原因很简单,可以自己想一下为什么 - 如果这里用数组去解,就不会有遍历顺序的问题
function convert(str) {
var result = '';
for (var i = str.length - 1; i >= 0; i--) {
if (str[i] === '&') {
result = '&' + result;
} else if (str[i] === '<') {
result = '<' + result;
} else if (str[i] === '>') {
result = '>' + result;
} else if (str[i] === "'") {
result = ''' + result;
} else if (str[i] === '"') {
result = '"' + result;
} else {
result = str[i] + result;
}
}
return result;
}
- 应该不难懂,没什么太多需要解释的。只需要注意一点,既然是从右向左遍历,所以不能写成
result +=
这样的形式,这样做是翻转字符串 - 尽量避免转义字符。见到过有些朋友喜欢一直用单引号或双引号,结果就会写成
'\''
或者"\""
这样的形式。个人不是很喜欢这种写法
- 对于这道题目的需求,既然存在一一对应关系,我们还可以用 Object 去处理,因为 Object 就是一一对应关系 (也可以称为 Map。注意这个 Map 不是数组方法,而是一种数据结构)
- 而且,既然我们直接操作字符串,那么最方便的替换方式就是用正则表达式了。这个正则表达式很容易写,
/[&<>'"]/g
,总共就只有这五种情况 - 但在用
replace
方法的时候,我们不能直接给出字符串表达式,因此需要给replace
一个回调函数。至于这个函数的参数,我们只需要用第一个,也就是匹配部分 -
replace
的回调函数返回值即字符串,也就是我们要替换成的目标字符串。在回调函数中,我们只需要通过上面创建好的 Object 去找就可以了 - 有的朋友可能会有疑问,能用特殊符号作为 Object 的
key
么?当然是可以的。任何可以被转换成为字符串的东西,都可以作为 Object 的key
function convert(str) {
var entityMap = {
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
};
return str.replace(/[&<>'"]/g, function(matched) {
return entityMap[matched];
})
}
- 上面提了一句,可以用数组来解这道题。这里不给出数组的循环解法,给出用
map
或reduce
的写法 -
map
方法会返回等长度的数组。我们会改数组中的元素,但不会影响数组的整体长度,因此这个办法是可行的 - 当然,如果用
map
,由于它还是返回数组,因此最后要join
起来,返回字符串 - 你还可以观察出,其实这道题的逻辑思路也符合我们以前说过的"把上一次计算结果用于下一次计算"。因此,这里用
reduce
也是没有问题的 -
reduce
这个方法的返回值,可以是数组、对象、数字、字符串等等。布尔值也是可以的,印象中我们在之前的题目里遇到过。至于到底返回什么,取决于你怎么写回调函数
function convert(str) {
const entityMap = {
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
};
return str.split('').map(char => entityMap[char] || char).join('');
}
function convert(str) {
const entityMap = {
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
};
return str.split('').reduce((prev, next) => {
return prev + (entityMap[next] || next);
}, '');
}