字符串
JavaScript 字符串用于存储和操作文本。通常由单引号或者双引号包围起来
-
内建属性length可返回字符串的长度。
-
字符串可以是对象,但是不要将字符串对象化,它会拖慢执行速度
const x = "Bill";
const y = new String("Bill");
// typeof x 将返回 string
// typeof y 将返回 object
关于`==`和`===`的区别:
当使用==的时候,相等字符串是相等的。(x==y)为true
当使用===的时候,(x===y)为false,因为x和y的类型不同,x为字符串,y为对象。
JS对象无法进行对比,比较两个JS将返回false
JS字符串方法
1. 查找字符串
- indexOf()方法,返回字符串中指定文本首次出现的索引(位置)
const str = "The full name of China is the People's Republic of China."
const pos = str.indexOf('e')
console.log(pos) //2
- lastIndexOf()方法返回指定文本在字符串中最后一次出现的索引
const posLast = str.lastIndexOf('i')
console.log(posLast) //53
如果没有找到文本的话,就都会返回-1
const str = "The full name of China is the People's Republic of China."
const pos = str.indexOf('HAHA')
console.log(pos) //-1
const posLast = str.lastIndexOf('H')
console.log(posLast) //-1
另外,两个方法都接受第二个参数,表示从哪一个索引开始检索
const str = "The full name of China is the People's Republic of China."
const pos = str.indexOf('f', 7)
console.log(pos) //16 此时检索到的是of中的f
lastIndexOf()同理
- search()方法收缩特定值的字符串,并返回匹配的位置
const str = 'My full name is DongHuan'
const pos = str.search('name')
console.log(pos) //8
两种方法,indexOf()
与search()
,是相等的。
这两种方法是不相等的。区别在于:
search()
方法无法设置第二个开始位置参数。indexOf()
方法无法设置更强大的搜索值(正则表达式)。
2. 提取部分字符串
slice(start,end)
substring(start,end)
substr(start,end)
- slice()提取字符串的某个部分并在新字符串中返回被提取的部分,该方法设置两个参数,slice(开始位置,结束位置)
const str = 'My full name is DongHuan'
const res = str.slice(0, 5)
console.log(res) //取的是索引为0,1,2,3,4,不包含5
如果某个参数为负数,表示从字符串结尾开始计数
const res = str.slice(-5, -3)
console.log(res) //取的是-5,-4 不包括-3
如果省略第二个参数,那么这方法会裁剪字符串的剩余部分
const res = str.slice(1)
console.log(res) // y full name is DongHuan 取得是索引0后面的
**当数组没有引用对象时,可以通过arr.slice(0)**对数组进行深拷贝。
这样写的好处:
1.对原数组进行深拷贝,这样进行一系列操作的时候就不影响原数组了;
2.将类数组对象转化为真正的数组对象:var anchorArray = [].slice.call(document.getElementsByTagName(‘a’), 0);
- substring()方法
这个方法类似于slice()方法,不同之处在于substring不能接受负的索引
- substr()方法
substr方法类似于slice(),不同之处在于第二个参数规定被提取部分的长度
const str = 'My full name is DongHuan'
const res = str.substr(3, 4)
console.log(res) //full 表示从索引为3,提取4个字符
如果省略第二个参数,则该 substr() 将裁剪字符串的剩余部分。
3. 替换字符串的内容
replace()方法用另一个值替换在字符串中指定的值
const str = 'My full name is DongHuan'
var res = str.replace('DongHuan', 'Dong-Huan')
console.log(res) //My full name is Dong-Huan
replace()方法不会改变调用它的字符串,它返回的是新字符串。
默认的,replace()只替换首个匹配
const str = 'My full name is DongHuan DongHuan'
var res = str.replace('DongHuan', 'Dong-Huan')
console.log(res) //My full name is Dong-Huan DongHuan
replace对大小写敏感name不会匹配NAME。如果执行大小写不敏感的替换,请使用正则表达式/i(大小写不敏感)
const str = 'My full name is DongHuan'
var res = str.replace(/FULL/i, 'all')
console.log(res) //My all name is DongHuan
如果需要替换全部匹配的话,就使用正则表达式的g
const str = 'My full name is donghuan donghuan'
var res = str.replace(/DONGHUAN/gi, 'Dong-Huan')
console.log(res) //My full name is Dong-Huan Dong-Huan
4. 转换为大写和小写
- 通过
toUpperCase()
把字符串转换为大写:
const text = 'Hello World'
const res = text.toUpperCase()
console.log(res) //HELLO WORLD
- 通过
toLowerCase()
把字符串转换为小写
const result = text.toLowerCase()
console.log(result) //hello world
5. 连接两个或多个字符串
- concat()连接字符串
const text1 = 'Hello'
const text2 = 'World'
const text3 = text1.concat(text2)
console.log(text3) //HelloWorld
concat()能代替加运算符
const text = 'hello' + ' ' + 'world' //hello world
const res = text1.concat(' ', text2) //hello world
所有字符串方法都会返回新字符串,他们不会修改原始字符串。也就是说,字符串是不可变的,字符串不能更改,只能替换
6. 删除字符串两端的空白
trim()
方法删除字符串两端的空白
const str = ' Hello world! '
console.log(str.trim()) //Hello world!
7. 提取字符串字符
- charAt(position)方法返回字符串中指定下标的字符串
const str = 'HELLO WORLD'
res = str.charAt(0)
console.log(res) //H
- charCodeAt(position)
const str = 'HELLO WORLD'
result = str.charCodeAt(0)
console.log(result) //A是65。 H是72
8. 属性访问
- 通过[]a对字符串的属性访问
const str = 'HELLO WORLD'
str[0] = 'A' //不会产生错误,但是不会工作
console.log(str[0])
9. 把字符串转换为数组
- 可以使用
split()
将字符串转换为数组
const str = 'a,b,c,d,e'
console.log(str.split(',')) //[ 'a', 'b', 'c', 'd', 'e' ]
console.log(str.split(' ')) //[ 'a,b,c,d,e' ]
console.log(str.split('|')) //[ 'a,b,c,d,e' ]
// 如果省略分隔符,被返回的数组将包含 index [0] 中的整个字符串。
console.log(str.split('')) //['a', ',', 'b', ',', 'c', ',', 'd', ',', 'e']
字符串
1. 反转字符串
- leetCode 344 反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
var reverseString = function(s) {
let left = 0,
right = s.length - 1
while (left < right) {
//交换字符
;
[s[left], s[right]] = [s[right], s[left]]
left++
right--
}
return s
}
console.log(reverseString(['h', 'e', 'l', 'l', 'o']))
- leetCode 501 反转字符串2
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
输入:s = "abcdefg", k = 2
输出:"bacdfeg"
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
const reverseStr = function(s, k) {
const len = s.length - 1
let resArr = s.split('')
for (let i = 0; i < len; i += 2 * k) {
let l = i
let r = i + k > len ? len : i + k - 1
while (l < r) {;
[resArr[l], resArr[r]] = [resArr[r], resArr[l]]
l++
r--
}
}
return resArr.join('')
}
console.log(reverseStr('abcd', 2))
2. 替换空格
- leetCode 05 剑指 Offer 05. 替换空格、
请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
思路
解法1
通过之前的介绍的replace()
const replaceSpace = function(s) {
const newS = s.replace(/ /g, '%20')
return newS
}
console.log(replaceSpace('We are happy'))
解法2
遍历字符串
const replaceSpace = function(s) {
let result = ''
for (let i = 0; i < s.length; i++) {
if (s[i] == ' ') {
result += '%20'
} else {
result += s[i]
}
}
return result
}
console.log(replaceSpace('We are happy.'))
解法3
双指针
/**
---因为 JS 中字符串无法被修改,一旦给字符串变量重新赋值,就要花费时间和空间去重新新建一个字符串.
1.将字符串转换为数组,然后统计其中的空格数量。
2.根据空格数量和原有字符串有效字符长度,计算出刚好存放替换后的字符长度的数组。
3.创建两个指针,一个指数组末尾,一个指字符串有效位的末尾,实现原地修改。
---一定要从后往前修改!
*/
var replaceSpace = function(s) {
s = s.split('')
let oldLen = s.length
let spaceCount = 0
for (let i = 0; i < oldLen; i++) {
if (s[i] === ' ') spaceCount++
}
s.length += spaceCount * 2
for (let i = oldLen - 1, j = s.length - 1; i >= 0; i--, j--) {
if (s[i] !== ' ') s[j] = s[i]
else {
s[j - 2] = '%'
s[j - 1] = '2'
s[j] = '0'
j -= 2
}
}
return s.join('')
}
3. 翻转字符串里的单词
- leetCode 151 翻转字符串里的单词
给你一个字符串 s ,逐个翻转字符串中的所有 单词 。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。
思路
解法一,使用库函数
/**
* @param {string} s
* @return {string}
*/
var reverseWords = function(s) {
s = s.split(' ').reverse()
let newArr = s.filter((d) => d != '')
return newArr.join(' ')
}
console.log(reverseWords(' hello world'))
- leetCode - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
输入: s = "abcdefg", k = 2
输出: "cdefgab"
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"
题解1:使用库函数
var reverseLeftWords = function(s, n) {
newS = s.substr(0, n)
s = s.slice(n) + newS
return s
}
console.log(reverseLeftWords('abcdefg', 2))
题解2: 为了使题更有意义,限制不能申请额外空间,只能在本串操作
可以通过局部反转+整体反转达到左旋转的目的
- 反转区间为前n的字串
- 反转区间为n到末尾的字串
- 反转整个字符串
const reverseLeftWords = function (s, n) {
const reverse = (str, left, right) => {
let strArr = str.split("");
for (; left < right; left++, right--) {
[strArr[left], strArr[right]] = [strArr[right], strArr[left]];
}
return strArr.join("");
}
s = reverse(s, 0, n - 1);
s = reverse(s, n, s.length - 1);
return reverse(s, 0, s.length - 1);
};
4. 重复的子字符串
- leetCode 459 重复的子字符串
给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
输入: "abab"
输出: True
解释: 可由子字符串 "ab" 重复两次构成。
思路
假设母串S是由子串x重复N次而成, 则 S+S则有子串x重复2N次, 那么现在有: S=Nx, S+S=2Nx, 其中N>=2。 如果条件成立, S+S=2Nx, 掐头去尾破坏2个x,S+S中还包含2*(N-1)x, 又因为N>=2, 因此S在(S+S)[1:-1]中必出现一次以上
-
将原字符串给出拷贝一遍组成新字符串;
-
掐头去尾留中间;
-
如果还包含原字符串,则满足题意。
举例:
s = abc|abc; // 2abc
s+s = abc|abc|abc|abc; // 4abc
s1 = a|bcabcabcab|c = bcabcabcab; // bc + 2*abc + ab
/**
* @param {string} s
* @return {boolean}
*/
var repeatedSubstringPattern = function(s) {
let temp = s+s
temp = temp.slice(1,-1)
return temp.indexOf(s) == -1? false:true
};