可以在字符串上使用 for in 循环吗?
Is it okay to use for in loop on a string?
只是想知道在字符串上使用 for in 循环是否可以接受。不确定是否会出现奇怪的结果或错误的做法,但我的解决方案至少在这个例子中有效。
编码练习题。另外,如果有人有办法改进我的解决方案,我愿意接受建议。
function firstNonRepeatingLetter(str) {
const lowerStr = str.toLowerCase();
for (let char in lowerStr) {
if (lowerStr.lastIndexOf(lowerStr[char]) === parseInt(char) &&
lowerStr.indexOf(lowerStr[char]) === parseInt(char)) {
return str[char];
}
}
return "";
}
编写一个名为 first_non_repeating_letter
的函数,接受 string
输入,returns 是字符串中任何地方都不重复的第一个字符。
示例:
firstNonRepeatingLetter('a') => 'a'
firstNonRepeatingLetter('stress') => 't'
firstNonRepeatingLetter('sTreSS') => 'T'
我认为一旦您在找到此任务的网站上解决了答案,它就会向您显示其他答案,因此您可以看到一些其他方法。
回到问题 - 你可以通过 .split()
方法将字符串转换为数组。 Array 提供了许多有用的方法,如 .filter()
、.map()
等,可以用来代替 for
循环。
使用 javascript maps
的算法方法:
是的,将 for loops
与字符串一起使用非常好。
const fn = (str) => {
res = [];
var ch = new Map();
for(var i = 0; i<str.length; i++) {
if(ch.has(str[i])) {
var val = ch.get(str[i])
val += 1
ch.set(str[i],val)
} else {
ch.set(str[i], 1)
}
}
ch.forEach((val, key) => {
if(val == 1) {
res.push(key)
}
})
return res[0]
}
console.log(fn('abcdeabcdef'))
当您的代码运行时,我建议采用索引来迭代字符串的字符。
但是您的方法通过使用 indexOf
和 lastIndexOf
对字符串进行了多次迭代。这可以通过使用存储最后找到的字符索引的循环来更改。
在另一个循环中,将相同字符的实际索引与存储的索引进行比较,如果相等则return。
function firstNonRepeatingLetter(str) {
var lowerStr = str.toLowerCase(),
hash = {},
i;
for (i = 0; i < lowerStr.length; i++)
hash[lowerStr[i]] = i;
for (i = 0; i < lowerStr.length; i++)
if (hash[lowerStr[i]] === i)
return str[i];
return "";
}
console.log(firstNonRepeatingLetter('a')); // a
console.log(firstNonRepeatingLetter('stress')); // t
console.log(firstNonRepeatingLetter('sTreSS')); // T
使用两个数组怎么样?首先,您可以使用 split
创建数组,也可以创建反向数组。
const origin = str.split('');
const reverse = [...origin].reverse();
然后,您可以使用filter
。
const nonRepeats = origin.filter((ele, index) => ele !== reverse[index]);
return nonRepeats[0];
为了回答标题中的问题,for..in
语句用于迭代可枚举的object属性(包括原型链中的成员)。虽然它在可迭代类型上 "works" ,但通常建议不要将它用作迭代 array-like 结构的方法,因为当您通常只查看数字索引。
例如,假设您稍后会填充功能或以其他方式修改 String 原型。
String.prototype.polyfill = () => {}
for(const prop in 'abc')
console.log(prop)
编辑:哦,快点。看起来我们两个人同时到达那里。然后我还会注意到正则表达式很擅长解决这类问题。 regex 101
const firstNonRepeatingLetter = str =>
(str && /(.)(?!.*?)/i.exec(str)[0]) || ''
;[
'a',
'stress',
'sTreSS'
]
.forEach(
str => console.log(firstNonRepeatingLetter(str))
)
要回答这个问题,是的,您可以将 for..in
与字符串一起使用。事实上,在大多数情况下,你不应该这样做。
for(i in X)
是这样工作的:
- 如果 X 不是对象,将其转换为相应的包装器(数字转换为
Number
,字符串转换为 String
)
- 对于 X 的每个 "enumerable property",将其名称分配给 i 和 运行 循环体
所以字符串被转换为 String
对象,正如您在控制台中看到的那样,它们就像数组一样:它们具有从 0 到长度 - 1 的数字属性,每个 属性包含相应的字符:
也就是说,是的,上面的逻辑对字符串来说工作得很好。
但是,如果您只想逐个字符地迭代字符串,可以使用更直接的方法:for..of
循环。
for(a of X)
从 X(可以是字符串、数组或任何 "iterable" 对象)中选取每个 元素(不是 属性) ) 并将其分配给 "a"。使用 for..of
,您的代码可以这样重构:
function firstNonRepeatingLetter(str) {
const lowerStr = str.toLowerCase();
for (let char of lowerStr) {
if (lowerStr.lastIndexOf(char) === lowerStr.indexOf(char))
return char;
}
return "";
}
只是想知道在字符串上使用 for in 循环是否可以接受。不确定是否会出现奇怪的结果或错误的做法,但我的解决方案至少在这个例子中有效。
编码练习题。另外,如果有人有办法改进我的解决方案,我愿意接受建议。
function firstNonRepeatingLetter(str) {
const lowerStr = str.toLowerCase();
for (let char in lowerStr) {
if (lowerStr.lastIndexOf(lowerStr[char]) === parseInt(char) &&
lowerStr.indexOf(lowerStr[char]) === parseInt(char)) {
return str[char];
}
}
return "";
}
编写一个名为 first_non_repeating_letter
的函数,接受 string
输入,returns 是字符串中任何地方都不重复的第一个字符。
示例:
firstNonRepeatingLetter('a') => 'a'
firstNonRepeatingLetter('stress') => 't'
firstNonRepeatingLetter('sTreSS') => 'T'
我认为一旦您在找到此任务的网站上解决了答案,它就会向您显示其他答案,因此您可以看到一些其他方法。
回到问题 - 你可以通过 .split()
方法将字符串转换为数组。 Array 提供了许多有用的方法,如 .filter()
、.map()
等,可以用来代替 for
循环。
使用 javascript maps
的算法方法:
是的,将 for loops
与字符串一起使用非常好。
const fn = (str) => {
res = [];
var ch = new Map();
for(var i = 0; i<str.length; i++) {
if(ch.has(str[i])) {
var val = ch.get(str[i])
val += 1
ch.set(str[i],val)
} else {
ch.set(str[i], 1)
}
}
ch.forEach((val, key) => {
if(val == 1) {
res.push(key)
}
})
return res[0]
}
console.log(fn('abcdeabcdef'))
当您的代码运行时,我建议采用索引来迭代字符串的字符。
但是您的方法通过使用 indexOf
和 lastIndexOf
对字符串进行了多次迭代。这可以通过使用存储最后找到的字符索引的循环来更改。
在另一个循环中,将相同字符的实际索引与存储的索引进行比较,如果相等则return。
function firstNonRepeatingLetter(str) {
var lowerStr = str.toLowerCase(),
hash = {},
i;
for (i = 0; i < lowerStr.length; i++)
hash[lowerStr[i]] = i;
for (i = 0; i < lowerStr.length; i++)
if (hash[lowerStr[i]] === i)
return str[i];
return "";
}
console.log(firstNonRepeatingLetter('a')); // a
console.log(firstNonRepeatingLetter('stress')); // t
console.log(firstNonRepeatingLetter('sTreSS')); // T
使用两个数组怎么样?首先,您可以使用 split
创建数组,也可以创建反向数组。
const origin = str.split('');
const reverse = [...origin].reverse();
然后,您可以使用filter
。
const nonRepeats = origin.filter((ele, index) => ele !== reverse[index]);
return nonRepeats[0];
为了回答标题中的问题,for..in
语句用于迭代可枚举的object属性(包括原型链中的成员)。虽然它在可迭代类型上 "works" ,但通常建议不要将它用作迭代 array-like 结构的方法,因为当您通常只查看数字索引。
例如,假设您稍后会填充功能或以其他方式修改 String 原型。
String.prototype.polyfill = () => {}
for(const prop in 'abc')
console.log(prop)
编辑:哦,快点。看起来我们两个人同时到达那里。然后我还会注意到正则表达式很擅长解决这类问题。 regex 101
const firstNonRepeatingLetter = str =>
(str && /(.)(?!.*?)/i.exec(str)[0]) || ''
;[
'a',
'stress',
'sTreSS'
]
.forEach(
str => console.log(firstNonRepeatingLetter(str))
)
要回答这个问题,是的,您可以将 for..in
与字符串一起使用。事实上,在大多数情况下,你不应该这样做。
for(i in X)
是这样工作的:
- 如果 X 不是对象,将其转换为相应的包装器(数字转换为
Number
,字符串转换为String
) - 对于 X 的每个 "enumerable property",将其名称分配给 i 和 运行 循环体
所以字符串被转换为 String
对象,正如您在控制台中看到的那样,它们就像数组一样:它们具有从 0 到长度 - 1 的数字属性,每个 属性包含相应的字符:
也就是说,是的,上面的逻辑对字符串来说工作得很好。
但是,如果您只想逐个字符地迭代字符串,可以使用更直接的方法:for..of
循环。
for(a of X)
从 X(可以是字符串、数组或任何 "iterable" 对象)中选取每个 元素(不是 属性) ) 并将其分配给 "a"。使用 for..of
,您的代码可以这样重构:
function firstNonRepeatingLetter(str) {
const lowerStr = str.toLowerCase();
for (let char of lowerStr) {
if (lowerStr.lastIndexOf(char) === lowerStr.indexOf(char))
return char;
}
return "";
}