วิธีที่เร็วที่สุดในการตรวจสอบสตริงมีสตริงย่อยอื่นใน JavaScript หรือไม่


163

ฉันกำลังทำงานกับปัญหาด้านประสิทธิภาพของ JavaScript ดังนั้นฉันอยากถามว่า: วิธีที่เร็วที่สุดในการตรวจสอบว่าสตริงมีซับสตริงอื่น (ฉันต้องการค่าบูลีน) หรือไม่ คุณช่วยแนะนำความคิดและตัวอย่างโค้ดตัวอย่างได้ไหม


คุณกำลังถามเกี่ยวกับสตริงย่อยคงที่หรือคุณต้องการนิพจน์ทั่วไป (ฉันสับสนเล็กน้อยจากการใช้regexแท็ก)
ทิม Pietzcker

1
โพสต์นี้จะเป็นประโยชน์ .. stackoverflow.com/questions/1789945/javascript-string-contain
mtk

วิธีการเกี่ยวกับการแยกสตริงกับอาร์เรย์รอบช่องว่างและทำแยกอาร์เรย์? stackoverflow.com/questions/1885557/…
giorgio79

คำตอบ:


315

คุณมีสองคนที่เป็นไปได้:

  1. นิพจน์ทั่วไป :

    (new RegExp('word')).test(str)
    // or
    /word/.test(str)
    
  2. indexOf:

    str.indexOf('word') !== -1

ดูเหมือนว่าการแสดงออกปกติจะเร็วขึ้น (อย่างน้อยใน Chrome 10)

การทดสอบประสิทธิภาพ - หญ้าทะเลสั้น
การทดสอบประสิทธิภาพ - หญ้าทะเลยาว


อัปเดต 2011:

ไม่สามารถพูดด้วยความมั่นใจว่าวิธีใดเร็วกว่า ความแตกต่างระหว่างเบราว์เซอร์นั้นมหาศาล ในขณะที่ Chrome 10 indexOfดูเหมือนว่าจะเร็วกว่าใน Safari 5 indexOfนั้นช้ากว่าวิธีอื่น ๆ อย่างเห็นได้ชัด

คุณต้องดูและลองด้วยตัวเอง ขึ้นอยู่กับความต้องการของคุณ ตัวอย่างเช่นการค้นหาแบบคำนึงถึงขนาดตัวพิมพ์เป็นวิธีที่รวดเร็วขึ้นด้วยนิพจน์ทั่วไป


อัปเดต 2018:

เพียงเพื่อช่วยชีวิตผู้คนไม่ให้ทำการทดสอบตัวเองนี่คือผลลัพธ์ปัจจุบันสำหรับเบราว์เซอร์ทั่วไปส่วนใหญ่เปอร์เซ็นต์บ่งบอกถึงประสิทธิภาพที่เพิ่มขึ้นจากผลลัพธ์ที่เร็วที่สุดถัดไป (ซึ่งแตกต่างกันระหว่างเบราว์เซอร์):

Chrome: indexOf (~ 98% เร็วกว่า) <-- wow
Firefox:แคช RegExp (เร็วขึ้น ~ 18%)
IE11:แคช RegExp (เร็วขึ้น 10%)
ขอบ:ดัชนีเร็วขึ้น (~ 18%)
Safari:แคช RegExp (~ 0.4% เร็วขึ้น)

โปรดทราบว่าRegExp ที่แคชคือ: var r = new RegExp('simple'); var c = r.test(str);เมื่อเทียบกับ:/simple/.test(str)


3
สิ่งนี้อาจเร็วขึ้นเล็กน้อยหากรู้ว่าข้อความต่อการค้นหานั้นเป็นที่รู้กันก่อน (เช่นไม่ได้เก็บไว้ในตัวแปร) เนื่องจาก regex สร้างขึ้นโดยเอ็นจิ้น JavaScript ในระหว่างการแยกวิเคราะห์ หากคุณต้องการค้นหาสตริงที่มีอยู่ในตัวแปรภายในตัวแปรสตริงอื่น indexOf นั้นเร็วที่สุดเพราะคุณต้องสร้างวัตถุ RegExp และประมวลผลสตริงเพื่อหลีกเลี่ยงอักขระพิเศษ ฯลฯ
Stephen Chung

จากประสบการณ์ indexOf สามารถเร็วขึ้นสำหรับการค้นหาแบบตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ถ้าคุณใช้. toLowerCase กับสิ่งที่คุณกำลังค้นหาก่อน
Hayk Saakian

ฉันกำลังเขียนแอพ Office 2013 โดยใช้ Office Javascript API ของ Microsoft และการใช้indexOfไม่ได้ผล ฉันไม่แน่ใจว่าทำไม ใช้ Regex แม้ว่า นี่คือกรณีขอบ แต่คนอื่น ๆ อาจพบปัญหาเดียวกัน
Andy Mercer

เหตุผลใด ๆ substr () ไม่ใช่หนึ่งในแนวทางแก้ไขที่เป็นไปได้? ฉันเดาว่ามันเร็วกว่าโซลูชัน RegEx ในหลาย ๆ สถานการณ์ ฉันไม่ทราบว่ามันเปรียบเทียบกับ indexOf () อย่างไร (ดังนั้นถ้าคุณปล่อยมันออกไปเพราะมันทำงานได้แย่กว่า indexOf () แล้วก็ไม่เป็นไรบางทีอาจเพิ่มหมายเหตุลงในเอฟเฟกต์นั้น) แก้ไข: ลิงก์ JSperf นี้น่าสนใจ ผล. เวอร์ชั่นย่อ: indexOf () เป็นวิธีที่เร็วที่สุดในทุกวิธี แต่สิ่งนี้อาจแตกต่างกันไปตามความยาวของสตริงและรูปแบบการทำซ้ำใด ๆ
Byson

1
@Bison: คุณสามารถใช้ substr ได้เฉพาะเมื่อคุณรู้ที่จะมอง ฉันมุ่งเน้นเฉพาะโซลูชันทั่วไปเท่านั้น
Felix Kling

17

มันใช้งานได้สำหรับคุณหรือไม่

string1.indexOf(string2) >= 0

แก้ไข: สิ่งนี้อาจไม่เร็วกว่า RegExp หาก string2 มีรูปแบบที่ซ้ำกัน ในบางเบราว์เซอร์ indexOf อาจช้ากว่า RegExp มาก ดูความคิดเห็น

แก้ไข 2: RegExp อาจเร็วกว่า indexOf เมื่อสตริงยาวมากและ / หรือมีรูปแบบซ้ำ ๆ ดูความคิดเห็นและคำตอบของ @ Felix


แต่วิธีนี้เปรียบเทียบกับวิธีอื่นได้อย่างไร นี่เป็นวิธีที่เร็วที่สุดหรือเป็นเพียงหนึ่งในหลาย ๆ วิธีในการทำเช่นนั้น?
Chii

สิ่งนี้ควรจะรวดเร็วเนื่องจากมีการใช้งานโดย JavaScript เอง (เช่นเรียกใช้รหัสเนทีฟ) วิธีอื่นใดที่ใช้รหัส JavaScript จะช้าลง หากคุณรู้ว่าสตริงที่แน่นอน regex อาจเร็วขึ้นเล็กน้อย (เนื่องจากเครื่องมือ JavaScript ไม่ต้องเดินผ่านเชนต้นแบบเพื่อค้นหา. indexOf)
Stephen Chung

หากคุณต้องการการค้นหาแบบคำนึงถึงขนาดตัวพิมพ์คุณต้องสร้างวัตถุ RegExp และโทรออกtestแน่นอน
Stephen Chung

3
เพิ่งทำการทดสอบใน Safari indexOfมีขนาดช้ากว่าวิธีอื่นใด ดังนั้นจึงไม่สามารถบอกได้ว่าวิธีใดเร็วกว่า มันแตกต่างจากเบราว์เซอร์เบราว์เซอร์
เฟลิกซ์คลิง

@ เฟลิกซ์นั่นเป็นข้อสังเกตที่ดี (อย่าเชื่อใจอะไรจนกว่าคุณจะลองด้วยตัวคุณเองจริงๆ)! ฉันคลุมเครือในการจดจำสิ่งที่กล่าวในสตริงที่มีรูปแบบการทำซ้ำหลายครั้ง regex ควรทำงานได้เร็วกว่าการใช้การเปรียบเทียบลูปแบบง่าย ๆ เพราะ regex ของคอมไพล์ลงในเครื่องของรัฐและสามารถติดตามย้อนกลับได้เร็วกว่าลูปธรรมดา ติดตามไปที่ตัวละครต่อไป +1 สำหรับทำการทดลองและนำสิ่งนี้ออกมา!
Stephen Chung

17

ที่เร็วที่สุด

  1. (ES6) ประกอบด้วย
    var string = "hello"
    substring = "lo";
    string.includes (substring);
  1. ES5 และindexOf ที่เก่ากว่า
    var string = "hello"
    substring = "lo";
    string.indexOf (สตริงย่อย)! == -1;

http://jsben.ch/9cwLJ

ป้อนคำอธิบายรูปภาพที่นี่


8

ใน ES6 includes()วิธีการจะใช้ในการกำหนดว่าอาจพบสตริงหนึ่งภายในสตริงอื่นกลับtrueหรือfalseตามความเหมาะสม

var str = 'To be, or not to be, that is the question.';

console.log(str.includes('To be'));       // true
console.log(str.includes('question'));    // true
console.log(str.includes('nonexistent')); // false

นี่คือjsperfระหว่าง

var ret = str.includes('one');

และ

var ret = (str.indexOf('one') !== -1);

ตามผลลัพธ์ที่แสดงใน jsperf ดูเหมือนว่าทั้งคู่จะทำงานได้ดี


ฉันสามารถใช้ "regex" ข้างในเป็นอาร์กิวเมนต์ 'include ได้หรือไม่ ไลค์: str.includes("x|y"); ค้นหาตัวอักษร "x" หรือ "y" ในการโทรเดียวกัน
ptkato

@Patrick คุณไม่สามารถใช้งานเอกสารregexดังกล่าวได้ หนึ่งในการทำงานรอบสำหรับคำถามของคุณstr.includes("x") || str.includes('y')
zangw

จากการปรับปรุงของ Chrome 59 JavaScript ทำให้indexOfเร็วกว่าincludes(สูงกว่า 1600% เร็วกว่า) ยังไม่ชัดเจนว่าความแตกต่างของการวนซ้ำ 44 ล้านครั้ง / วินาทีและ777+ ล้านตัวต่อวินาทีนั้นส่งผลกระทบต่อประสิทธิภาพการทำงานจริงอย่างไรมือถือน่าจะได้รับประโยชน์มากพอที่indexOfควรจะเป็นตัวเลือกในอุดมคติ
Chad Levy

7

ฉันได้พบว่าการใช้ง่ายสำหรับวงวนมากกว่าองค์ประกอบทั้งหมดในสตริงและเปรียบเทียบโดยใช้charAtดำเนินการได้เร็วกว่าหรือindexOf Regexรหัสและหลักฐานที่มีอยู่ในJSPerf

ETA: indexOfและcharAtทั้งคู่ทำงานได้แย่มากใน Chrome Mobile ตามข้อมูลขอบเขตของเบราว์เซอร์ที่อยู่ใน jsperf.com


แปลกที่ฟังก์ชั่นทำมือนั้นดีกว่าแบบในตัว แต่ฉันเดาว่านี่เป็นเพราะเข็มเป็นตัวละครเพียงตัวเดียว ยัง ...
มอส

ทดสอบใน Chrome Mobile 36.0.1985.57 บน Apple iPad (iOS 7.1.1) IndexOf เร็วขึ้น ขออภัย
rpax

@rpax CharAt ยังคงเร็วกว่าบนทุกแพลตฟอร์มอย่างมาก (อ้างอิงจากประวัติของ jsperf) ยกเว้น Chrome Mobile ซึ่งทั้ง IndexOf และ CharAt ทำงานได้ไม่ดีเท่ากันเมื่อเทียบกับเดสก์ท็อป
wpg4665

1
ฉันต้องการดูว่าสิ่งนี้มีประสิทธิภาพอย่างไรใน NodeJS และนี่ไม่ใช่ตัวอย่างที่ดีเพราะคุณกำลังมองหาอักขระหนึ่งตัวเทียบกับสตริงย่อย
qodeninja

นี่ไม่ใช่คำตอบที่ถูกต้องเลย คุณไม่ได้ค้นหาซับสตริงเฉพาะการปรากฏตัวของอักขระเดี่ยวเท่านั้น
Henrik Myntti

3

สำหรับการค้นหาสตริงอย่างง่าย ๆ การใช้วิธี indexOf () และการใช้ regex นั้นค่อนข้างเหมือนกัน: http://jsperf.com/substring - ดังนั้นเลือกอันไหนที่เขียนง่ายกว่า



1

มันเป็นวิธีง่ายๆในการใช้.match()วิธีการสตริง

var re = /(AND|OR|MAYBE)/;
var str = "IT'S MAYBE BETTER WAY TO USE .MATCH() METHOD TO STRING";
console.log('Do we found something?', Boolean(str.match(re)));

ขอให้คุณเป็นวันที่ดีนะ!


4
ไม่มีเหตุผลที่matchเมื่อมีtestวิธี ... ตรวจสอบคำตอบด้านบน
Bergi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.