Câu hỏi Làm thế nào để kiểm tra xem một chuỗi "StartsWith" một chuỗi?


Làm thế nào tôi sẽ viết tương đương với C # của String.StartsWith trong JavaScript?

var haystack = 'hello world';
var needle = 'he';

//haystack.startsWith(needle) == true

Lưu ý: Đây là một câu hỏi cũ, và như đã chỉ ra trong các ý kiến ​​ECMAScript 2015 (ES6) đã giới thiệu .startsWith phương pháp. Tuy nhiên, tại thời điểm viết bản cập nhật này (2015) hỗ trợ trình duyệt chưa hoàn thành.


1547
2018-03-14 20:12


gốc




Các câu trả lời:


Bạn có thể sử dụng ECMAScript 6's String.prototype.startsWith() phương pháp, nhưng nó chưa được hỗ trợ trong tất cả các trình duyệt. Bạn sẽ muốn sử dụng một shim / polyfill để thêm nó trên các trình duyệt không hỗ trợ nó. Tạo triển khai tuân thủ tất cả các chi tiết được trình bày trong thông số kỹ thuật hơi phức tạp và phiên bản được xác định trong câu trả lời này sẽ không làm; nếu bạn muốn một shim trung thành, sử dụng một trong hai:

Khi bạn đã kích hoạt phương thức (hoặc nếu bạn chỉ hỗ trợ các trình duyệt và các công cụ JavaScript đã có sẵn), bạn có thể sử dụng nó như sau:

"Hello World!".startsWith("He"); // true

var haystack = "Hello world";
var prefix = 'orl';
haystack.startsWith(prefix); // false

1655
2018-03-14 20:19



JSPerf có nguồn gốc startsWith: jsperf.com/js-startwith-prototype/8 - JimmyBoh
@gtournie tại sao sẽ startWith là một trong những phương pháp tồi tệ nhất để kiểm tra nếu một chuỗi bắt đầu bằng một chuỗi? (xem bình luận của bạn ở đây: stackoverflow.com/questions/646628/…) bạn nhiệt tình hơn khi so sánh nhân vật trên mỗi nhân vật. Tôi hy vọng các trình biên dịch đủ thông minh KHÔNG tạo ra một chuỗi cho mỗi chuỗi [index] bởi vì, nếu bạn chỉ cần viết điều này: character = string [0] nó sẽ phân bổ một đối tượng, vô cùng hiệu quả hơn so với sử dụng startsWith (startsWith sẽ không cấp phát bộ nhớ nào ) - Martijn Scheffer
@MartijnScheffer: Câu trả lời đã được chỉnh sửa nhiều lần kể từ khi tôi trả lời và hiện đã hoàn toàn khác (tôi đã xóa nhận xét của mình;). Tôi đồng ý rằng phương thức startsWith của ECMAScript 6 là cách tốt nhất để làm điều đó. - gtournie
@GrahamLaight, khi bạn nói được hỗ trợ bởi 'IE', có lẽ bạn có nghĩa là bởi Edge. developer.mozilla.org/en/docs/Web/JavaScript/Reference/… - Marcus
@Marcus, xin lỗi nếu tôi sai - thông tin của tôi đến từ: w3schools.com/jsref/jsref_startswith.asp - Graham Laight


Một lựa chọn khác với .lastIndexOf:

haystack.lastIndexOf(needle, 0) === 0

Điều này trông ngược qua haystack cho một sự xuất hiện của needle bắt đầu từ chỉ mục 0 của haystack. Nói cách khác, nó chỉ kiểm tra nếu haystack bắt đầu với needle.

Về nguyên tắc, điều này sẽ có lợi thế về hiệu suất so với một số cách tiếp cận khác:

  • Nó không tìm kiếm toàn bộ haystack.
  • Nó không tạo ra một chuỗi tạm thời mới và sau đó loại bỏ nó ngay lập tức.

1226
2018-01-02 16:14



Bạn không chắc chắn trường hợp nào @ rfcoder89 đang thực hiện - jsfiddle.net/jkzjw3w2/1 - Gulfaraz Yasin
@ rfcoder89 Lưu ý tham số thứ hai của lastIndexOf: "aba".lastIndexOf ("a") là 2 khi bạn chỉ ra, nhưng "aba".lastIndexOf ("a", 0) là 0, đúng - maxpolk
Cảm ơn bạn rất nhiều. String.startsWith không hoạt động trên Android Lollipop WebView, nhưng đoạn mã lastIndexOf này không hoạt động! - Herman
với lastIndexOf chuỗi được tìm kiếm từ đầu đến đầu để nó tìm kiếm toàn bộ chuỗi: do đó, tính không hiệu quả của nó phát triển cho các chuỗi rất dài để tìm kiếm. - willy wonka
@ willywonka Không, nó không phải nếu bạn có 0 startIndex, nó được tìm kiếm từ 0 pos và đó là kiểm tra duy nhất. Toàn bộ chuỗi chỉ được tìm kiếm nếu từIndex> = str.length. - greene


data.substring(0, input.length) === input

569
2018-03-14 20:14



@ANeves Tôi nghi ngờ nó phụ thuộc mạnh vào trình duyệt và dữ liệu được sử dụng. Xem câu trả lời của Ben Weaver cho các phép đo thực tế. Trên trình duyệt tôi hiện đang chạy (Chrome 12.0.742 trên Windows), chuỗi con thắng thành công và chiến thắng regex chuẩn bị cho thất bại. - cobbal
@cobbal Có thể. Nhưng .lastIndexOf(input, 0) so sánh N ký tự đầu tiên, trong khi .substring(0, input.length) === input đếm N, chất nền dữ liệu để chiều dài N, và sau đó so sánh những ký tự N. Trừ khi có tối ưu hóa mã, phiên bản thứ hai này không thể nhanh hơn phiên bản thứ hai. Tuy nhiên, đừng hiểu lầm tôi, tôi sẽ không bao giờ tìm được một thứ gì đó tốt hơn bạn đề xuất. :) - ANeves
@ANeves Nhưng .lastIndexOf trên một chuỗi dài sẽ trả về false sẽ lặp qua toàn bộ chuỗi (O (N)), trong khi trường hợp .substring lặp qua chuỗi có khả năng nhỏ hơn nhiều. Nếu bạn mong đợi phần lớn thành công hoặc chỉ có đầu vào nhỏ, .lastIndexOf có thể nhanh hơn - nếu không .substring có thể nhanh hơn. .substring cũng có rủi ro ngoại lệ nếu đầu vào dài hơn chuỗi đang được kiểm tra. - Chris Moschini
@ ChrisMoschini, đừng quên rằng giải pháp của Mark Byers đã lastIndexOf bắt đầu từ chỉ mục 0, không phải là kết thúc. Điều đó đã vấp ngã tôi, ban đầu. Tuy nhiên, việc kiểm tra xem chuỗi nào bắt đầu với một nhiệm vụ phổ biến là JavaScript thực sự phải có API thích hợp cho nó, không phải tất cả các thành ngữ và lựa chọn thay thế mà bạn thấy trên trang này, tuy nhiên chúng thông minh. - Randall Cook
Tôi thích giải pháp của Cobbal hơn Mark. Ngay cả khi đánh dấu là nhanh hơn, và một thủ thuật ấn tượng bằng cách sử dụng params, nó rất khó đọc so với chuỗi con. - ThinkBonobo


Không có hàm trợ giúp, chỉ cần sử dụng regex .test phương pháp:

/^He/.test('Hello world')

Để làm điều này với một chuỗi động chứ không phải là một chuỗi cứng (giả sử rằng chuỗi sẽ không chứa bất kỳ ký tự kiểm soát regexp):

new RegExp('^' + needle).test(haystack)

Bạn nên kiểm tra Có một hàm RegExp.escape trong Javascript không? nếu khả năng tồn tại, các ký tự điều khiển regexp xuất hiện trong chuỗi.


180
2018-01-04 00:59





Tôi chỉ muốn thêm ý kiến ​​của tôi về điều này.

Tôi nghĩ chúng ta chỉ có thể sử dụng như thế này:

var haystack = 'hello world';
var needle = 'he';

if (haystack.indexOf(needle) == 0) {
  // Code if string starts with this substring
}

50
2018-02-12 14:47



Câu trả lời Mark Byers được so sánh với hiệu suất của ba phương pháp tiếp cận chính xác khác nhau của @relfor. Cách tiếp cận chính xác này không được ưa chuộng vì nó đòi hỏi tìm kiếm toàn bộ chuỗi. - maxpolk
@ maxpolk tôi nghĩ indexOf sẽ ngừng tìm kiếm toàn bộ chuỗi khi tìm thấy lần xuất hiện đầu tiên. Tôi đã kiểm tra nó. - Mr.D
Nếu sự xuất hiện đầu tiên không được tìm thấy ngay từ đầu, cách tiếp cận này bắt đầu phát triển không hiệu quả lâu hơn nó tiếp tục tìm kiếm nó, có khả năng tìm kiếm cho đến khi nó kết thúc, thay vì từ bỏ sớm hơn nhiều. Bởi vì có tiềm năng không hiệu quả, nó không được ưa chuộng trong ba phương pháp chính xác. - maxpolk
@ Mr.D Và nếu không có trận đấu? - momo
@momomo Sau đó thêm else mã. - Mr.D


Giải pháp tốt nhất:

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

Và đây là endsWith nếu bạn cần điều đó:

function endsWith(str, word) {
    return str.indexOf(word, str.length - word.length) !== -1;
}

Đối với những người thích thử nghiệm nó thành chuỗi: 

String.prototype.startsWith || (String.prototype.startsWith = function(word) {
    return this.lastIndexOf(word, 0) === 0;
});

String.prototype.endsWith   || (String.prototype.endsWith = function(word) {
    return this.indexOf(word, this.length - word.length) !== -1;
});

Sử dụng: 

"abc".startsWith("ab")
true
"c".ensdWith("c") 
true

42
2018-04-26 21:56



Tôi nghĩ rằng bạn đã trộn lẫn lastIndexOf và indexOf trong các hàm của bạn - startsWith phải trả về str.indexOf (word, 0) === 0; - Richard Matheson
@RichardMatheson vấn đề với việc sử dụng indexOf là nếu nó không khớp lúc bắt đầu, nó sẽ tiếp tục tìm kiếm toàn bộ chuỗi, theo đó lastIndexOf bắt đầu từ độ dài của từ và quay trở lại không. Hiểu rồi? - momo
Ahh có ý nghĩa bây giờ - tôi đã không chú ý đến các chỉ số bạn đang sử dụng. Thủ thuật rất hay! - Richard Matheson


Dưới đây là một cải tiến nhỏ đối với giải pháp của CMS:

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

Kiểm tra xem chức năng đã tồn tại trong trường hợp một trình duyệt trong tương lai thực hiện nó trong mã nguồn gốc hay nó được thực hiện bởi một thư viện khác. Ví dụ, Thư viện Prototype triển khai thực hiện chức năng này.

Sử dụng ! hơi nhanh hơn và ngắn gọn hơn === 0 mặc dù không thể đọc được.


37
2018-05-27 02:54



Điều này có thể trở thành một vấn đề: Nếu việc thực hiện đã diễn ra khác với hành vi của tôi, điều này sẽ phá vỡ ứng dụng của tôi. - Christoph Wurm
Điều này có vấn đề O (N) được thảo luận ở đây stackoverflow.com/questions/646628/javascript-startswith/… - Chris Moschini
sử dụng! có rất lộn xộn - Jonny Leeds
-1; thêm cái này vào String.prototype là một ý tưởng tồi bởi vì nó không đến bất cứ đâu gần tuân thủ spec cho String.prototype.startsWith. Bất kỳ mã nào cố gắng sử dụng phương pháp ES6 đều có thể bị lỗi nếu bạn đang thực hiện việc này; nó cũng có thể xem xét nếu phương pháp đã được xác định, thấy rằng nó là (xấu, bởi bạn) và không thêm vào một shim spec-compliant, dẫn đến hành vi không chính xác sau này. - Mark Amery
Điều này là không tốt. - momo