如何检查一个string“StartsWith”另一个string?
我将如何编写相当于C#的String.StartsWith
在JavaScript中?
var haystack = 'hello world'; var needle = 'he'; //haystack.startsWith(needle) == true
注意:这是一个老问题,正如在ECMAScript 2015(ES6)的评论中指出的.startsWith
方法一样。 不过,在编写本次更新(2015年) 浏览器支持的时间还远远没有完成 。
您可以使用ECMAScript 6的String.prototype.startsWith()
方法,但是它尚未在所有浏览器中受支持 。 您将需要使用填充/填充将其添加到不支持它的浏览器上。 创build符合规范中规定的所有细节的实现有点复杂,并且在这个答案中定义的版本将不会执行; 如果你想要一个忠实的垫片,使用:
- 马蒂亚斯Bynens的
String.prototype.startsWith
垫片 ,或 - es6-shim ,尽可能多的ES6规格,包括
String.prototype.startsWith
。
一旦你清除了方法(或者你只支持已经有的浏览器和JavaScript引擎),你可以像这样使用它:
"Hello World!".startsWith("He"); // true var haystack = "Hello world"; var prefix = 'orl'; haystack.startsWith(prefix); // false
.lastIndexOf
另一种select:
haystack.lastIndexOf(needle, 0) === 0
这从haystack
的索引0
开始,通过haystack
向后看。 换句话说,它只会检查needle
是否以needle
开始。
原则上,这应该比其他方法具有性能优势:
- 它不search整个
haystack
。 - 它不会创build一个新的临时string,然后立即丢弃它。
data.substring(0, input.length) === input
如果没有辅助函数,只需使用正则expression式的.test
方法:
/^He/.test('Hello world')
使用dynamicstring而不是硬编码(假设string不包含任何正则expression式控制字符):
new RegExp('^' + needle).test(haystack)
你应该检查在Javascript中是否有RegExp.escape函数? 如果可能存在正则expression式控制字符出现在string中。
我只是想补充一下我的意见。
我想我们可以这样使用:
var haystack = 'hello world'; var needle = 'he'; if (haystack.indexOf(needle) == 0) { // Code if string starts with this substring }
这是CMS解决scheme的一个小改进:
if(!String.prototype.startsWith){ String.prototype.startsWith = function (str) { return !this.indexOf(str); } } "Hello World!".startsWith("He"); // true var data = "Hello world"; var input = 'He'; data.startsWith(input); // true
检查函数是否已经存在,以防将来的浏览器以本地代码实现它,或者是否由另一个库实现。 例如,Prototype库已经实现了这个function。
使用!
虽然没有可读性,但是比=== 0
稍快且更简洁。
最佳解决scheme
function startsWith(str, word) { return str.lastIndexOf(word, 0) === 0; } startsWith("aaa", "a") true startsWith("aaa", "ab") false startsWith("abc", "abc") true startsWith("abc", "c") false startsWith("abc", "a") true startsWith("abc", "ba") false startsWith("abc", "ab") true
如果你也需要这个,
function endsWith(str, word) { return str.indexOf(word, str.length - word.length) !== -1; }
也检查出underscore.string.js 。 它带有一些有用的stringtesting和操作方法,包括一个startsWith
方法。 从文档:
startsWith
_.startsWith(string, starts)
该方法检查
string
是否以starts
。_("image.gif").startsWith("image") => true
我最近问自己同样的问题。
有多种可能的解决scheme,这里有3个有效的解决scheme:
-
s.indexOf(starter) === 0
-
s.substr(0,starter.length) === starter
-
s.lastIndexOf(starter, 0) === 0
(在看到Mark Byers的回答后添加) -
使用循环:
function startsWith(s,starter) { for (var i = 0,cur_c; i < starter.length; i++) { cur_c = starter[i]; if (s[i] !== starter[i]) { return false; } } return true; }
我还没有遇到使用循环的最后一个解决scheme。
令人惊讶的是,这个解决scheme的performance远远优于前三。
这里是我为了得出这个结论而进行的jsperftesting: http ://jsperf.com/startswith2/2
和平
ps:ecmascript 6(和谐)为string引入了本地startsWith
方法。
只要想想,如果他们想到在初始版本中包含这个非常需要的方法,那么会节省多less时间。
更新
正如Steve指出的那样(对这个答案的第一个评论),如果给定的前缀比整个string短,上面的自定义函数将会抛出一个错误。 他已经修复了这个问题,并添加了一个循环优化,可以在http://jsperf.com/startswith2/4上查看。;
请注意,Steve包含了2个循环优化,其中第一个显示了更好的性能,因此我将在下面发布该代码:
function startsWith2(str, prefix) { if (str.length < prefix.length) return false; for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i) continue; return i < 0; }
由于这是如此受欢迎,我认为值得指出的是,在ECMA 6中有一个实现这种方法的方法,并且为了防止未来的问题和眼泪,准备使用“官方”的polyfill。
幸运的是,Mozilla的专家为我们提供了一个:
https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position) { position = position || 0; return this.indexOf(searchString, position) === position; }; }
请注意,这有一个过渡到ECMA 6优雅地忽略的优势。
性能最好的解决scheme是停止使用库调用,只是认识到你正在使用两个数组。 手卷实现既短又快,比我在这里看到的其他所有解决scheme都快。
function startsWith2(str, prefix) { if (str.length < prefix.length) return false; for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i) continue; return i < 0; }
有关性能比较(成功和失败),请参阅http://jsperf.com/startswith2/4 。 (请确保你检查了可能超过我的更高版本。)
我刚刚了解到这个string库:
包括js文件,然后像这样使用S
variables:
S('hi there').endsWith('hi there')
它也可以通过安装在NodeJS中使用:
npm install string
然后要求它作为S
variables:
var S = require('string');
网页也有链接到替代string库,如果这个不喜欢你的幻想。
var str = 'hol'; var data = 'hola mundo'; if (data.length >= str.length && data.substring(0, str.length) == str) return true; else return false;
基于这里的答案,这是我现在使用的版本,因为它似乎给出了基于JSPerftesting的最佳性能(function完备,据我所知)。
if(typeof String.prototype.startsWith != 'function'){ String.prototype.startsWith = function(str){ if(str == null) return false; var i = str.length; if(this.length < i) return false; for(--i; (i >= 0) && (this[i] === str[i]); --i) continue; return i < 0; } }
这是基于startsWith2从这里: http : //jsperf.com/startswith2/6 。 我添加了一个微小的性能改进,此后还添加了一个比较string为空或未定义的检查,并将其转换为使用CMS的答案中的技术添加到string原型。
请注意,这个实现不支持在这个Mozilla开发者networking页面中提到的“position”参数,但是这似乎并不是ECMAScript提案的一部分。
我正在寻找性能,所以我通过jsperf来运行函数。 我testing了针对主题的function和search不同大小的string,看来所有的方法都performance出不同的input性能。 一般模式是性能随着searchstring长度的增加而降低。
总的来说,胜利者是最好的方法。
您也可以通过创build您自己的原型/扩展到数组原型,也可以返回以string开头的数组的所有成员
Array.prototype.mySearch = function (target) { if (typeof String.prototype.startsWith != 'function') { String.prototype.startsWith = function (str){ return this.slice(0, str.length) == str; }; } var retValues = []; for (var i = 0; i < this.length; i++) { if (this[i].startsWith(target)) { retValues.push(this[i]); } } return retValues; };
并使用它:
var myArray = ['Hello', 'Helium', 'Hideout', 'Hamster']; var myResult = myArray.mySearch('Hel'); // result -> Hello, Helium
如果你正在使用startsWith()
和endsWith()
那么你必须小心前导空格。 是完整的例子:
var Str1 = " Your String Value Here.!! "; // Starts With & Ends With leading Spaces var Str2 = Str1.trim(); // Removes All Spaces by using Trim() function Something like this --> "Your String Value Here.!!" if (Str2.startsWith("Your")) // returns TRUE if (Str2.endsWith("Here.!!")) // returns TRUE if (Str1.startsWith("Your")) // returns FALSE due to the leading spaces… if (Str1.endsWith("Here.!!")) // returns FALSE due to trailing spaces…