จะตรวจสอบว่าสตริงมีข้อความจากอาร์เรย์ของสตริงย่อยใน JavaScript ได้อย่างไร?


163

ตรงไปตรงมาสวย ในจาวาสคริปต์ฉันต้องตรวจสอบว่าสตริงมีสตริงย่อยใด ๆ ที่อยู่ในอาร์เรย์หรือไม่


map()HTML5-JavaScript-version ใหม่ไม่มีฟังก์ชั่นใช่หรือไม่ ผมจำได้ว่ามีบางสิ่งบางอย่างที่อ่านในหัวข้อที่ ...
มาร์ติน Hennings

@ Martin: จุดดีไม่มากเป็นmap จะช่วย แต่คุณจะต้องผ่านฟังก์ชั่น somesome
TJ Crowder

คำตอบ:


223

ไม่มีอะไรในตัวที่จะทำเพื่อคุณคุณจะต้องเขียนฟังก์ชั่นสำหรับมัน

หากคุณรู้ว่าสตริงไม่มีอักขระใด ๆ ที่มีความพิเศษในนิพจน์ทั่วไปคุณสามารถโกงได้เช่นนี้

if (new RegExp(substrings.join("|")).test(string)) {
    // At least one match
}

... ซึ่งสร้างนิพจน์ทั่วไปซึ่งเป็นชุดของทางเลือกสำหรับสตริงย่อยที่คุณกำลังมองหา (เช่นone|two) และการทดสอบเพื่อดูว่ามีการจับคู่ใด ๆ กับพวกเขาหรือไม่ แต่หากใด ๆ ของสตริงย่อยมีอักขระใด ๆ ที่พิเศษ ใน regexes ( *, [ฯลฯ ) คุณจะต้องหลบหนีพวกเขาก่อนและคุณทำได้ดีกว่าเพียงแค่ทำลูปที่น่าเบื่อแทน

ตัวอย่างสด:


ในความคิดเห็นเกี่ยวกับคำถามมาร์ตินถามเกี่ยวกับArray.prototype.mapวิธีการใหม่ใน ECMAScript5 mapไม่ได้ช่วยอะไรมากนัก แต่someเป็น:

if (substrings.some(function(v) { return str.indexOf(v) >= 0; })) {
    // There's at least one
}

ตัวอย่างสด:

คุณมีเพียงการใช้งานที่สอดคล้องกับ ECMAScript5 แม้ว่าจะเป็นเรื่องเล็กน้อยที่จะใช้ polyfill


อัปเดตในปี 2020 : someตัวอย่างสามารถทำได้ง่ายขึ้นด้วยฟังก์ชั่นลูกศร (ES2015 +) และคุณอาจใช้includesแทนindexOf:

if (substrings.some(v => str.includes(v))) {
    // There's at least one
}

ตัวอย่างสด:

หรือแม้แต่โยนbindมันถึงแม้ว่าสำหรับฉันฟังก์ชั่นลูกศรนั้นสามารถอ่านได้มากขึ้น:

if (substrings.some(str.includes.bind(str))) {
    // There's at least one
}

ตัวอย่างสด:


2
"ใจคุณก็ไม่ได้หมายความว่าค่าใช้จ่ายบางอย่าง ..." แต่ไม่มีอะไรที่จะดูแลเกี่ยวกับ
TJ Crowder

คุณสามารถขยายการแก้ปัญหาดังกล่าวข้างต้นโดยการเอาตัวละคร regex ทั้งหมดยกเว้น new RegExp(substrings.join("|").replace(/[^\w\s^|]/gi, '')).test(string)'|':
user007

การใช้ indexOf อาจคลุมเครือเกินไปและให้ผลลัพธ์ที่แปลก มันสามารถนำไปจับคู่กับสตริงโดยใช้ตัวดำเนินการของเท่ากับ เช่น('disconnect'.indexOf('connect') >= 0) === trueแต่('disconnect' === 'conenct') === false
kylewelsby

@halfcube: ใช่มั้ย ฉันไม่เข้าใจคุณฉันกลัว ไม่มีอะไรในคำตอบข้างต้นแสดงให้เห็นว่า'disconnect' === 'connect'จะมีอะไร falseแต่ นอกจากนี้indexOfไม่คลุมเครือมันชัดเจนมากแน่นอน
TJ Crowder

indexOfจะจับคู่ทั้งสองdisconnectและconnectในกรณีที่ฉันมีประสบการณ์กรณีเหล่านี้เป็นสองกรณีที่แตกต่างกันที่ฉันต้องการแสดงผลลัพธ์ในเงื่อนไข
kylewelsby

54
var yourstring = 'tasty food'; // the string to check against


var substrings = ['foo','bar'],
    length = substrings.length;
while(length--) {
   if (yourstring.indexOf(substrings[length])!=-1) {
       // one of the substrings is in yourstring
   }
}

50

ทางออกเดียว

substringsArray.some(substring=>yourBigString.includes(substring))

ส่งคืนtrue\falseถ้าสตริงย่อยexists\does'nt exist

ต้องการการสนับสนุน ES6


วิธีการแก้ปัญหาที่ยอดเยี่ยมโดยใช้ฟังก์ชั่นลูกศร
GuerillaRadio

7
คุณเด็ก ... ย้อนกลับไปตอนที่ฉันยังเป็นเด็กเราต้องใช้สิ่งเหล่านี้เรียกว่า 'for' loops และคุณต้องใช้หลายบรรทัดและรู้ว่าอาร์เรย์ของคุณเป็นแบบ 1 หรือศูนย์ใช่ใช่ ... ครึ่งเวลาที่คุณได้รับ มันผิดและต้องแก้จุดบกพร่องและมองหา bugger เล็ก ๆ ที่เรียกว่า 'i'
aamarks

25
function containsAny(str, substrings) {
    for (var i = 0; i != substrings.length; i++) {
       var substring = substrings[i];
       if (str.indexOf(substring) != - 1) {
         return substring;
       }
    }
    return null; 
}

var result = containsAny("defg", ["ab", "cd", "ef"]);
console.log("String was found in substring " + result);

1
ง่ายที่สุดที่จะเข้าใจ!
Daryl H

รวมทั้งส่งกลับคำที่เกิดขึ้นครั้งแรกของคำในสตริงซึ่งมีประโยชน์มาก ไม่เพียง แต่เป็นของจริง / เท็จ
Kai Noack

20

สำหรับคนที่ Googling

คำตอบที่มั่นคงควรจะเป็น

const substrings = ['connect', 'ready'];
const str = 'disconnect';
if (substrings.some(v => str === v)) {
   // Will only return when the `str` is included in the `substrings`
}

2
หรือสั้นกว่า: ถ้า (substrings.some (v => v === str)) {
kofifus

10
โปรดทราบว่านี่เป็นคำตอบสำหรับคำถามที่แตกต่างกันเล็กน้อยซึ่งถามว่าสตริงมีข้อความจากอาร์เรย์ของสตริงย่อยหรือไม่ รหัสนี้ตรวจสอบว่าสตริงเป็นหนึ่งในสตริงย่อยหรือไม่ ขึ้นอยู่กับสิ่งที่มีความหมายโดย "มี" ฉันคิดว่า
fcrick

8
var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = 0, len = arr.length; i < len; ++i) {
    if (str.indexOf(arr[i]) != -1) {
        // str contains arr[i]
    }
}

แก้ไข: หากลำดับการทดสอบไม่สำคัญคุณสามารถใช้สิ่งนี้ (ด้วยตัวแปรลูปเดียวเท่านั้น):

var str = "texttexttext";
var arr = ["asd", "ghj", "xtte"];
for (var i = arr.length - 1; i >= 0; --i) {
    if (str.indexOf(arr[i]) != -1) {
        // str contains arr[i]
    }
}

ตัวอย่างแรกของคุณไม่จำเป็นต้องตัวแปรเพียงตรวจสอบlen i < arr.length
GreySage

3

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


สมมติว่าเรามีรายการสตริงย่อย 100 รายการ วิธีไหนจะมีประสิทธิภาพมากกว่า: RegExp หรือ loop
Diyorbek Sadullayev

3

ฟังก์ชัน Javascript เพื่อค้นหาอาร์เรย์ของแท็กหรือคำหลักโดยใช้สตริงการค้นหาหรืออาร์เรย์ของสตริงการค้นหา (ใช้ES5 บางวิธีการที่หลากหลายและการES6 ลูกศรฟังก์ชั่น )

// returns true for 1 or more matches, where 'a' is an array and 'b' is a search string or an array of multiple search strings
function contains(a, b) {
    // array matches
    if (Array.isArray(b)) {
        return b.some(x => a.indexOf(x) > -1);
    }
    // string match
    return a.indexOf(b) > -1;
}

ตัวอย่างการใช้งาน:

var a = ["a","b","c","d","e"];
var b = ["a","b"];
if ( contains(a, b) ) {
    // 1 or more matches found
}

2

ไม่ใช่ที่ฉันแนะนำให้คุณไปและขยาย / แก้ไขStringต้นแบบ แต่นี่คือสิ่งที่ฉันทำ:

String.prototype.includes ()

String.prototype.includes = function (includes) {
    console.warn("String.prototype.includes() has been modified.");
    return function (searchString, position) {
        if (searchString instanceof Array) {
            for (var i = 0; i < searchString.length; i++) {
                if (includes.call(this, searchString[i], position)) {
                    return true;
                }
            }
            return false;
        } else {
            return includes.call(this, searchString, position);
        }
    }
}(String.prototype.includes);

console.log('"Hello, World!".includes("foo");',          "Hello, World!".includes("foo")           ); // false
console.log('"Hello, World!".includes(",");',            "Hello, World!".includes(",")             ); // true
console.log('"Hello, World!".includes(["foo", ","])',    "Hello, World!".includes(["foo", ","])    ); // true
console.log('"Hello, World!".includes(["foo", ","], 6)', "Hello, World!".includes(["foo", ","], 6) ); // false


2

จากการแก้ปัญหาของ TJ Crowder ฉันสร้างต้นแบบเพื่อจัดการกับปัญหานี้:

Array.prototype.check = function (s) {
  return this.some((v) => {
    return s.indexOf(v) >= 0;
  });
};

2
substringsArray.every(substring=>yourBigString.indexOf(substring) === -1)

สำหรับการสนับสนุนอย่างเต็มที่;)


2

คำตอบที่ดีที่สุดอยู่ที่นี่: กรณีนี้ไม่รู้สึกเช่นกัน

    var specsFilter = [.....];
    var yourString = "......";

    //if found a match
    if (specsFilter.some((element) => { return new RegExp(element, "ig").test(yourString) })) {
        // do something
    }

1

ใช้ underscore.js หรือ lodash.js คุณสามารถทำสิ่งต่อไปนี้บนอาร์เรย์ของสตริง:

var contacts = ['Billy Bob', 'John', 'Bill', 'Sarah'];

var filters = ['Bill', 'Sarah'];

contacts = _.filter(contacts, function(contact) {
    return _.every(filters, function(filter) { return (contact.indexOf(filter) === -1); });
});

// ['John']

และในสตริงเดียว:

var contact = 'Billy';
var filters = ['Bill', 'Sarah'];

_.every(filters, function(filter) { return (contact.indexOf(filter) >= 0); });

// true

1

นี่มันสายไปแล้ว แต่ฉันเพิ่งเจอปัญหานี้ ในโครงการของฉันฉันใช้สิ่งต่อไปนี้เพื่อตรวจสอบว่าสตริงอยู่ในอาร์เรย์หรือไม่:

["a","b"].includes('a')     // true
["a","b"].includes('b')     // true
["a","b"].includes('c')     // false

วิธีนี้คุณสามารถใช้อาร์เรย์ที่กำหนดไว้ล่วงหน้าและตรวจสอบว่ามีสตริงอยู่หรือไม่:

var parameters = ['a','b']
parameters.includes('a')    // true

1

สร้างคำตอบของ TJ Crowder

ใช้ Escape RegExp เพื่อทดสอบการเกิด "อย่างน้อยหนึ่งครั้ง" ของสตริงย่อยอย่างน้อยหนึ่งรายการ

function buildSearch(substrings) {
  return new RegExp(
    substrings
    .map(function (s) {return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');})
    .join('{1,}|') + '{1,}'
  );
}


var pattern = buildSearch(['hello','world']);

console.log(pattern.test('hello there'));
console.log(pattern.test('what a wonderful world'));
console.log(pattern.test('my name is ...'));


1

หากคุณกำลังทำงานกับรายการย่อยที่มีความยาวประกอบด้วย "คำ" แบบเต็มคั่นด้วยช่องว่างหรืออักขระทั่วไปอื่น ๆ คุณอาจจะฉลาดในการค้นหาเล็กน้อย

อันดับแรกแบ่งสตริงของคุณเป็นกลุ่มของ X จากนั้น X + 1 แล้ว X + 2, ... , สูงสุด Y. X และ Y ควรเป็นจำนวนคำในสตริงย่อยของคุณด้วยคำที่น้อยที่สุดและมากที่สุดตามลำดับ ตัวอย่างเช่นถ้า X คือ 1 และ Y คือ 4 "Alpha Beta Gamma Delta" จะกลายเป็น:

"Alpha" "Beta" "Gamma" "Delta"

"Alpha Beta" "Beta Gamma" "Gamma Delta"

"Alpha Beta Gamma" "เดลต้าแกมมาเบต้า"

"Alpha Beta Gamma Delta"

หาก X เป็น 2 และ Y เป็น 3 คุณจะไม่ต้องป้อนแถวแรกและแถวสุดท้าย

ตอนนี้คุณสามารถค้นหารายการนี้ได้อย่างรวดเร็วหากคุณใส่ลงในชุด (หรือแผนที่) เร็วกว่าการเปรียบเทียบสตริง

ข้อเสียคือคุณไม่สามารถค้นหาวัสดุพิมพ์เช่น "ta Gamm" แน่นอนว่าคุณสามารถอนุญาตให้ทำได้โดยแยกตัวละครแทนคำ แต่คุณมักจะต้องสร้างชุดใหญ่และเวลา / หน่วยความจำที่ใช้ในการทำเช่นนั้นมีมากกว่าประโยชน์


1

สำหรับการสนับสนุนอย่างเต็มที่ (เพิ่มเติมจาก verions ของ@ricca )

wordsArray = ['hello', 'to', 'nice', 'day']
yourString = 'Hello. Today is a nice day'.toLowerCase()
result = wordsArray.every(w => yourString.includes(w))
console.log('result:', result)


0

คุณสามารถตรวจสอบสิ่งนี้:

<!DOCTYPE html>
<html>
   <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script>
         $(document).ready(function(){
         var list = ["bad", "words", "include"] 
         var sentence = $("#comments_text").val()

         $.each(list, function( index, value ) {
           if (sentence.indexOf(value) > -1) {
                console.log(value)
            }
         });
         });
      </script>
   </head>
   <body>
      <input id="comments_text" value="This is a bad, with include test"> 
   </body>
</html>

-1
let obj = [{name : 'amit'},{name : 'arti'},{name : 'sumit'}];
let input = 'it';

ใช้ตัวกรอง:

obj.filter((n)=> n.name.trim().toLowerCase().includes(input.trim().toLowerCase()))

กรุณาเยี่ยมชมและตรวจสอบวิธีการที่จะตอบคำถาม
Yunus Temurlenk

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