PHP - lấy tất cả các khóa từ một mảng bắt đầu bằng một chuỗi nhất định


84

Tôi có một mảng trông như thế này:

array(
  'abc' => 0,
  'foo-bcd' => 1,
  'foo-def' => 1,
  'foo-xyz' => 0,
  // ...
)

Làm cách nào để chỉ lấy các phần tử bắt đầu bằng foo-?


3
Có một mảng với các tiền tố như thế này là một mùi mã. Trích xuất các giá trị đó vào một đối tượng chứa các giá trị này hoặc ít nhất làm cho tiền tố trỏ đến một mảng và thêm các giá trị vào đó.
Gordon

Câu trả lời:


20
$arr_main_array = array('foo-test' => 123, 'other-test' => 456, 'foo-result' => 789);

foreach($arr_main_array as $key => $value){
    $exp_key = explode('-', $key);
    if($exp_key[0] == 'foo'){
         $arr_result[] = $value;
    }
}

if(isset($arr_result)){
    print_r($arr_result);
}

18
Trước khi bạn thực hiện giải pháp này, giải pháp dưới đây là tốt hơn. Không bao giờ sử dụng các hàm mảng trong đó hàm chuỗi đơn giản là đủ. Các hàm chuỗi nhanh hơn WAY. Điều này sẽ 'tụt hậu' với các mảng lớn.
Martijn

2
Tôi không thấy điểm bùng nổ các phím mảng thành mảng. Chúng là chuỗi và câu hỏi ban đầu chỉ là hỏi về tiền tố chuỗi. Ngoài ra OP đang yêu cầu "các phần tử" thay vì chỉ các giá trị, vì vậy kết quả được lập chỉ mục số sẽ trở nên vô dụng - các khóa rõ ràng là quan trọng ở đây, với các giá trị (có lẽ) là cờ 1/0 ẩn danh.
Jason

126

Cách tiếp cận chức năng:

Chọn một array_filter_keyloại chức năng từ các nhận xét trong http://php.net/array_filter hoặc viết của riêng bạn. Sau đó, bạn có thể làm:

$array = array_filter_key($array, function($key) {
    return strpos($key, 'foo-') === 0;
});

Cách tiếp cận theo thủ tục:

$only_foo = array();
foreach ($array as $key => $value) {
    if (strpos($key, 'foo-') === 0) {
        $only_foo[$key] = $value;
    }
}

Cách tiếp cận thủ tục sử dụng các đối tượng:

$i = new ArrayIterator($array);
$only_foo = array();
while ($i->valid()) {
    if (strpos($i->key(), 'foo-') === 0) {
        $only_foo[$i->key()] = $i->current();
    }
    $i->next();
}

20
Lưu ý PHP 5.6 thêm cờ ARRAY_FILTER_USE_KEY array_filter(), bạn có thể sử dụng cờ này thay vì cung cấp một array_filter_key()hàm tùy chỉnh .
Jason

4
Bạn có thể vui lòng thêm hàm array_filter_key vào ví dụ của mình không? Tôi liên tục gặp lỗi và phải đọc lại bài viết của bạn nhiều lần trước khi nhận ra lỗi của mình. Không khó chỉ cần đăng mã, tiết kiệm một cú nhấp chuột và tiết kiệm thời gian cho ai đó khắc phục sự cố. Cảm ơn.
Chris Sprague,

38

Đây là cách tôi sẽ làm, mặc dù tôi không thể cho bạn một lời khuyên hiệu quả hơn trước khi hiểu bạn muốn làm gì với những giá trị bạn nhận được.

$search = "foo-";
$search_length = strlen($search);
foreach ($array as $key => $value) {
    if (substr($key, 0, $search_length) == $search) {
        ...use the $value...
    }
}

2
Bạn cũng có thể sử dụng:foreach ($array as $key => $value) { if (0 === strpos($key, 'foo-')) { ...use the $value... } }
Iago

"4" ở đây cần được điều chỉnh thành bất kỳ độ dài "foo-" nào.
Jason

21

Đơn giản là tôi đã sử dụng array_filterhàm để đạt được giải pháp như sau

<?php

$input = array(
    'abc' => 0,
    'foo-bcd' => 1,
    'foo-def' => 1,
    'foo-xyz' => 0,
);

$filtered = array_filter($input, function ($key) {
    return strpos($key, 'foo-') === 0;
}, ARRAY_FILTER_USE_KEY);

print_r($filtered);

Đầu ra

Array
(
    [foo-bcd] => 1
    [foo-def] => 1
    [foo-xyz] => 0
)

Để kiểm tra trực tiếp https://3v4l.org/lJCse


1
Lưu ý rằng điều này cần ít nhất PHP 5.6.0 (do sử dụng hằng số ARRAY_FILTER_USE_KEY). Trong các phiên bản trước, bạn có thể sử dụng: [code]
Netsurfer

20

Từ PHP 5.3, bạn có thể sử dụng preg_filterhàm: tại đây

$unprefixed_keys = preg_filter('/^foo-(.*)/', '$1', array_keys( $arr ));

// Result:
// $unprefixed_keys === array('bcd','def','xyz')

14
foreach($arr as $key => $value)
{
   if(preg_match('/^foo-/', $key))
   {
        // You can access $value or create a new array based off these values
   }
}

3
Một regex không thực sự cần thiết trong trường hợp này. Phương pháp substr là hơi hiệu quả hơn
jfoucher

2
@jfoucher: Đúng là như vậy, tuy nhiên, về mặt cá nhân, nó dễ đọc hơn.
Tim Cooper

2
Nó có thể linh hoạt hơn, nhưng đi kèm với cái giá phải trả là cần phải thoát khỏi các ký tự thai đặc biệt nếu bạn không muốn thực hiện đối sánh biểu thức chính quy. Vì vậy, sử dụng một cách thận trọng. Tôi sẽ đề nghị bạn chỉ sử dụng RE nếu bạn cần RE.
Jason

7

Sửa đổi đối với phương pháp tiếp cận Chức năng của erisco ,

array_filter($signatureData[0]["foo-"], function($k) {
    return strpos($k, 'foo-abc') === 0;
}, ARRAY_FILTER_USE_KEY);

điều này đã làm việc cho tôi.


Bất kỳ sự khác biệt nào về hiệu suất hoặc tính hữu dụng so với phiên bản array_filter_key do @erisco cung cấp?
Jeffrey the Giraffe,

Không. Tôi đoán sẽ không có bất kỳ sự khác biệt nào về hiệu suất. @MaciekSemik
Keyur

1
Đây là một hàm cốt lõi của PHP nên được ưu tiên hơn.
Jeremy John

3

Ngoài câu trả lời của @Suresh Velusamy ở trên (cần ít nhất PHP 5.6.0), bạn có thể sử dụng câu trả lời sau nếu bạn đang sử dụng phiên bản PHP trước:

<?php

$input = array(
    'abc' => 0,
    'foo-bcd' => 1,
    'foo-def' => 1,
    'foo-xyz' => 0,
);

$filtered = array_filter(array_keys($input), function($key) {
    return strpos($key, 'foo-') === 0;
});

print_r($filtered);

/* Output:
Array
(
    [1] => foo-bcd
    [2] => foo-def
    [3] => foo-xyz
)
// the numerical array keys are the position in the original array!
*/

// if you want your array newly numbered just add:
$filtered = array_values($filtered);

print_r($filtered);

/* Output:
Array
(
    [0] => foo-bcd
    [1] => foo-def
    [2] => foo-xyz
)
*/

Xin lưu ý (hoặc ít nhất là đối với tôi) rằng điều này chỉ trả về khóa mảng phù hợp. Câu trả lời dưới đây của @ suresh-velusamy trích xuất mảng thực tế với $key => $valuecặp ban đầu . Đó là tuyên bố trong đầu ra của câu trả lời này, nhưng vẫn chưa được đề cập một cách rõ ràng
Martie
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.