Sử dụng một mảng làm kim trong strpos


89

Làm thế nào để bạn sử dụng strposcho một mảng kim khi tìm kiếm một chuỗi? Ví dụ:

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';

if(strpos($string, $find_letters) !== false)
{
    echo 'All the letters are found in the string!';
}

Vì khi dùng cái này sẽ không được, nếu có cái này thì tốt quá

Câu trả lời:


134

@Lưu đoạn mã cập nhật từ http://www.php.net/manual/en/ Chức năng.strpos.php#107351

function strposa($haystack, $needles=array(), $offset=0) {
        $chr = array();
        foreach($needles as $needle) {
                $res = strpos($haystack, $needle, $offset);
                if ($res !== false) $chr[$needle] = $res;
        }
        if(empty($chr)) return false;
        return min($chr);
}

Cách sử dụng:

$string = 'Whis string contains word "cheese" and "tea".';
$array  = array('burger', 'melon', 'cheese', 'milk');

if (strposa($string, $array, 1)) {
    echo 'true';
} else {
    echo 'false';
}

sẽ trở lại true, bởi vì array "cheese".

Cập nhật: Mã được cải thiện với điểm dừng khi tìm thấy kim đầu tiên:

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
        if(strpos($haystack, $query, $offset) !== false) return true; // stop on first true result
    }
    return false;
}
$string = 'Whis string contains word "cheese" and "tea".';
$array  = array('burger', 'melon', 'cheese', 'milk');
var_dump(strposa($string, $array)); // will return true, since "cheese" has been found

1
@Arnaud, nông cụ được đề xuất của bạn là gì?
Binyamin

5
Tôi không chắc, nhưng có lẽ chúng ta có thể tiến lên trong chuỗi từ $ offset và dừng lại khi tìm thấy kim đầu tiên. Hãy nghĩ về một văn bản lớn chứa đầy "a". Lấy $ kim = [a, b]. Hàm của bạn strposasẽ chạy qua tất cả văn bản, nhưng nó không cần thiết! Tôi có hiểu không?
Arnaud

Cảm ơn @Arnaud về đề xuất tính năng! Tôi hoàn toàn đồng ý với tầm quan trọng đề xuất của bạn và đã cập nhật câu trả lời của tôi với ví dụ mã cải tiến.
Binyamin

Đây không phải là chính xác những gì tôi muốn nói, bởi vì với hàm mới $ kim = [b, a] của bạn vẫn chưa có vấn đề gì và ngoài ra hàm không còn trả về vị trí của lần xuất hiện đầu tiên nữa. Hãy để tôi giải thích thêm một chút. Giả sử rằng chuỗi là "ABCDEF", và các kim là C và F. Những gì chúng ta có thể làm là chạy qua chuỗi: A, B ... C! Chúng tôi phát hiện C, vì vậy chúng tôi dừng lại ở đây và chúng tôi có thể trả lại vị trí của lần xuất hiện đầu tiên của một chiếc kim, là 2. Nó có thể hoạt động với nhiều hơn các chuỗi ký tự đơn, nhưng tôi chưa nghĩ về cách triển khai chính xác.
Arnaud

1
Tôi đã cải thiện mã bằng cách thay đổi foreach($needle as $k => $query) { if(strpos($haystack, $query, $offset) !== false) return $k; }, vì vậy nó trả về khóa của mục phù hợp để xử lý thêm.
James Cameron

51

str_replace nhanh hơn đáng kể.

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
$match = (str_replace($find_letters, '', $string) != $string);

lỗi cú pháp: 1 dấu ngoặc đóng quá nhiều ở dòng số 3 (Tôi không thể sửa nó trực tiếp trong đoạn mã trên do yêu cầu chỉnh sửa> 6 ký tự;))
richey

1
Rất tiếc, cái đó đã bị đứt. Đã sửa ngay. Chúc mừng những người đứng đầu!
Leon

6
một trong những giải pháp tuyệt vời nhất!
andys

18

Đoạn mã dưới đây không chỉ hiển thị cách thực hiện mà còn đưa nó vào một hàm dễ sử dụng trong tương lai. Nó được viết bởi "jesda". (Tôi tìm thấy nó trực tuyến)

Mã PHP:

<?php
/* strpos that takes an array of values to match against a string
 * note the stupid argument order (to match strpos)
 */
function strpos_arr($haystack, $needle) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $what) {
        if(($pos = strpos($haystack, $what))!==false) return $pos;
    }
    return false;
}
?>

Sử dụng:

$needle = array('something','nothing');
$haystack = "This is something";
echo strpos_arr($haystack, $needle); // Will echo True

$haystack = "This isn't anything";
echo strpos_arr($haystack, $needle); // Will echo False 

Tôi tin rằng điều này chỉ trả lại vị trí đầu tiên mà nó tìm thấy. Bất kỳ đề xuất nào về cách điều chỉnh nó để trả lại vị trí của mọi cây kim trong đống cỏ khô?
Chaya Cooper

7

Bạn có thể lặp qua mảng và đặt giá trị "cờ" nếu strpostrả về false.

$flag = false;
foreach ($find_letters as $letter)
{
    if (strpos($string, $letter) === false)
    {
        $flag = true;
    }
}

Sau đó, kiểm tra giá trị của $flag.


6
không nên nó được !== flase?
Joe Huang

Nó phải là! == false. Trừ khi bạn phá vỡ ngay sau khi bạn đặt cờ của mình thành true. Và sau đó sẽ phải giải thích lá cờ như là một Cảnh báo rằng một cái kim không nằm trong đống cỏ khô. Điều đó có nghĩa là những gì bạn đang cố gắng đạt được là kiểm tra xem tất cả kim tiêm của bạn có nằm trong đống cỏ khô hay không. Đó không phải là câu hỏi. Vì vậy .. vâng. ! == false
Kevin Gagnon

5

Nếu bạn chỉ muốn kiểm tra xem một số ký tự nhất định có thực sự nằm trong chuỗi hay không, hãy sử dụng strtok :

$string = 'abcdefg';
if (strtok($string, 'acd') === $string) {
    // not found
} else {
    // found
}

Câu trả lời đáng kinh ngạc - Thực thi nhanh hơn NHIỀU so với nhiều strpos (), ví dụ: if (strpos ($ string, "a")! == false && strpos ($ string, "c")! == false && strpos ($ string, " d ")! == false)
Bộ môn Hóa học có một không hai,

5

Câu hỏi đặt ra là ví dụ được cung cấp chỉ là "ví dụ" hay chính xác những gì bạn đang tìm kiếm? Có rất nhiều câu trả lời hỗn hợp ở đây và tôi không hiểu mức độ phức tạp của câu được chấp nhận.

Để tìm xem có BẤT KỲ nội dung nào của dãy kim có tồn tại trong chuỗi hay không và nhanh chóng trả về true hoặc false:

$string = 'abcdefg';

if(str_replace(array('a', 'c', 'd'), '', $string) != $string){
    echo 'at least one of the needles where found';
};

Nếu vậy, hãy ghi công @Leon cho điều đó.

Để tìm xem TẤT CẢ các giá trị của dãy kim có tồn tại trong chuỗi hay không, như trong trường hợp này, cả ba 'a', 'b''c'PHẢI có mặt, giống như bạn đề cập là "ví dụ"

echo 'Tất cả các chữ cái được tìm thấy trong chuỗi!';

Nhiều câu trả lời ở đây nằm ngoài ngữ cảnh đó, nhưng tôi nghi ngờ rằng nội dung của câu hỏi mà bạn đã đánh dấu là đã được giải quyết. Ví dụ: Câu trả lời được chấp nhận là một cái kim của

$array  = array('burger', 'melon', 'cheese', 'milk');

Điều gì sẽ xảy ra nếu tất cả những từ đó PHẢI được tìm thấy trong chuỗi?

Sau đó, bạn thử một số "not accepted answers"trên trang này.


Điều này hoạt động hoàn hảo đối với tôi vì tôi đang tìm kiếm mảng của mình chứa các chuỗi con. Tôi đã được cứu khỏi việc viết lệnh sql như "% $ string%"
Maurice Elagu

4

Biểu thức này tìm kiếm tất cả các chữ cái:

count(array_filter( 
    array_map("strpos", array_fill(0, count($letters), $str), $letters),
"is_int")) == count($letters)

3

Bạn có thể thử điều này:

function in_array_strpos($word, $array){

foreach($array as $a){

    if (strpos($word,$a) !== false) {
        return true;
    }
}

return false;
}

1

Bạn cũng có thể thử sử dụng strpbrk () để phủ định (không tìm thấy chữ cái nào):

$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';

if(strpbrk($string, implode($find_letters)) === false)
{
    echo 'None of these letters are found in the string!';
}

1

Đây là cách tiếp cận của tôi. Lặp lại các ký tự trong chuỗi cho đến khi tìm thấy khớp. Trên một dãy kim lớn hơn, điều này sẽ tốt hơn câu trả lời được chấp nhận bởi vì nó không cần phải kiểm tra mọi kim để xác định rằng đã tìm thấy khớp.

function strpos_array($haystack, $needles = [], $offset = 0) {
    for ($i = $offset, $len = strlen($haystack); $i < $len; $i++){
        if (in_array($haystack[$i],$needles)) {
            return $i;
        }
    }
    return false;
}

Tôi đã đánh giá tiêu chuẩn này so với câu trả lời được chấp nhận và với một mảng hơn 7, $needlesđiều này nhanh hơn đáng kể .


0

Với mã sau:

$flag = true;
foreach($find_letters as $letter)
    if(false===strpos($string, $letter)) {
        $flag = false; 
        break;
    }

Sau đó, kiểm tra giá trị của $flag. Nếu có true, tất cả các chữ cái đã được tìm thấy. Nếu không, đó là false.


0

Tôi đang viết một câu trả lời mới hy vọng sẽ giúp ích cho bất kỳ ai đang tìm kiếm điều tương tự như tôi.

Điều này hoạt động trong trường hợp "Tôi có nhiều kim và tôi đang cố gắng sử dụng chúng để tìm một chuỗi đơn". và đây là câu hỏi tôi đã xem qua để tìm ra điều đó.

    $i = 0;
    $found = array();
    while ($i < count($needle)) {
        $x = 0;
        while ($x < count($haystack)) {
            if (strpos($haystack[$x], $needle[$i]) !== false) {
                array_push($found, $haystack[$x]);
            }
            $x++;
        }
        $i++;
    }

    $found = array_count_values($found);

Mảng $foundsẽ chứa danh sách tất cả các kim phù hợp, mục của mảng có giá trị đếm cao nhất sẽ là (các) chuỗi bạn đang tìm kiếm, bạn có thể lấy nó bằng:

print_r(array_search(max($found), $found));

0

Trả lời @binyamin và @Timo .. (không đủ điểm để thêm nhận xét ..) nhưng kết quả không chứa vị trí ..
Đoạn mã dưới đây sẽ trả về vị trí thực tế của phần tử đầu tiên là mục đích của strpos làm. Điều này hữu ích nếu bạn đang mong đợi tìm được chính xác 1 kết quả phù hợp. Nếu bạn đang mong đợi tìm được nhiều kết quả phù hợp, thì vị trí tìm thấy đầu tiên có thể vô nghĩa.

function strposa($haystack, $needle, $offset=0) {
    if(!is_array($needle)) $needle = array($needle);
    foreach($needle as $query) {
      $res=strpos($haystack, $query, $offset);
      if($res !== false) return $res; // stop on first true result
    }
    return false;
}

0

Chỉ là một bản nâng cấp từ các câu trả lời trên

function strsearch($findme, $source){
    if(is_array($findme)){
        if(str_replace($findme, '', $source) != $source){
            return true;
        }
    }else{
        if(strpos($source,$findme)){
            return true;
        }
    }
    return false;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.