[php] PHP에서 다차원 배열의 키 => 값으로 검색하는 방법
다차원 배열에서 키 값 쌍이 발견 된 모든 하위 배열을 얻는 빠른 방법이 있습니까? 배열의 깊이를 말할 수 없습니다.
간단한 예제 배열 :
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>"cat 1")
);
key = name 및 value = “cat 1″을 검색하면 함수가 다음을 반환해야합니다.
array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>3,name=>"cat 1")
);
가장 깊은 수준으로 내려 가려면 함수가 재귀 적이어야한다고 생각합니다.
답변
암호:
function search($array, $key, $value)
{
$results = array();
if (is_array($array)) {
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
$results = array_merge($results, search($subarray, $key, $value));
}
}
return $results;
}
$arr = array(0 => array(id=>1,name=>"cat 1"),
1 => array(id=>2,name=>"cat 2"),
2 => array(id=>3,name=>"cat 1"));
print_r(search($arr, 'name', 'cat 1'));
산출:
Array
(
[0] => Array
(
[id] => 1
[name] => cat 1
)
[1] => Array
(
[id] => 3
[name] => cat 1
)
)
효율성이 중요한 경우 모든 재귀 호출에서 결과를 $results
배열을 병합하지 않고 동일한 임시 배열 에 저장하도록 다음과 같이 작성할 수 있습니다.
function search($array, $key, $value)
{
$results = array();
search_r($array, $key, $value, $results);
return $results;
}
function search_r($array, $key, $value, &$results)
{
if (!is_array($array)) {
return;
}
if (isset($array[$key]) && $array[$key] == $value) {
$results[] = $array;
}
foreach ($array as $subarray) {
search_r($subarray, $key, $value, $results);
}
}
핵심은 search_r
네 번째 매개 변수를 값이 아닌 참조로 사용한다는 것입니다. 앰퍼샌드&
가 중요합니다.
참고 : 당신이 PHP의 이전 버전이있는 경우에 당신은에서 통과 참조에 의한 부분을 지정해야 호출 에 search_r
보다는 선언합니다. 즉, 마지막 줄은 search_r($subarray, $key, $value, &$results)
입니다.
답변
방법에 대한 SPL의 대신 버전? 입력 내용을 저장합니다.
// I changed your input example to make it harder and
// to show it works at lower depths:
$arr = array(0 => array('id'=>1,'name'=>"cat 1"),
1 => array(array('id'=>3,'name'=>"cat 1")),
2 => array('id'=>2,'name'=>"cat 2")
);
//here's the code:
$arrIt = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
foreach ($arrIt as $sub) {
$subArray = $arrIt->getSubIterator();
if ($subArray['name'] === 'cat 1') {
$outputArray[] = iterator_to_array($subArray);
}
}
좋은 점은 기본적으로 동일한 코드가 RecursiveArrayIterator 대신 RecursiveDirectoryIterator를 사용하여 디렉토리를 반복한다는 것입니다. SPL은 근사치입니다.
SPL에 대한 유일한 문제는 웹에 잘못 문서화되어 있다는 것입니다. 그러나 몇몇 PHP 서적은 특히 Pro PHP; 더 많은 정보를 얻으려면 Google을 사용하십시오.
답변
<?php
$arr = array(0 => array("id"=>1,"name"=>"cat 1"),
1 => array("id"=>2,"name"=>"cat 2"),
2 => array("id"=>3,"name"=>"cat 1")
);
$arr = array_filter($arr, function($ar) {
return ($ar['name'] == 'cat 1');
//return ($ar['name'] == 'cat 1' AND $ar['id'] == '3');// you can add multiple conditions
});
echo "<pre>";
print_r($arr);
?>
참조 : http://php.net/manual/en/function.array-filter.php
답변
이 답변에 대한 최적화 팁이 필요한 사람, 특히 John Kugelman의 위의 훌륭한 답변을 위해이 업데이트를 게시했습니다.
그의 게시 된 기능은 정상적으로 작동하지만 12 000 행 결과 집합을 처리하기 위해이 시나리오를 최적화해야했습니다. 이 기능은 모든 레코드를 통과하는 데 8 초가 걸렸습니다.
검색을 중지하고 일치하는 것이 발견되면 반환하는 기능이 필요했습니다. 즉, customer_id를 검색하면 결과 집합에 하나만 있다는 것을 알고 다차원 배열에서 customer_id를 찾으면 반환하려고합니다.
다음은이 기능의 속도 최적화 및 훨씬 단순화 된 버전입니다. 다른 버전과 달리 배열의 한 가지 깊이 만 처리 할 수 있고 재귀하지 않으며 여러 결과를 병합하지 않아도됩니다.
// search array for specific key = value
public function searchSubArray(Array $array, $key, $value) {
foreach ($array as $subarray){
if (isset($subarray[$key]) && $subarray[$key] == $value)
return $subarray;
}
}
이로 인해 12 000 개의 레코드를 1.5 초로 일치시키는 작업이 중단되었습니다. 여전히 비용이 많이 들지만 훨씬 더 합리적입니다.
답변
if (isset($array[$key]) && $array[$key] == $value)
빠른 버전에 대한 사소한 개선.
답변
다차원 배열에서 선형 검색 알고리즘 (위의 선형)은 깊이가 전체 배열을 순회하는 데 필요한 반복 횟수를 증가 시키므로 복잡성이 복잡해 지므로주의하십시오. 예 :
array(
[0] => array ([0] => something, [1] => something_else))
...
[100] => array ([0] => something100, [1] => something_else100))
)
적절한 알고리즘을 사용하여 원하는 것을 찾는 데 최대 200 회 반복해야합니다 (바늘이 [100] [1] 인 경우).
이 경우 선형 알고리즘은 O (n) (전체 배열의 총 요소 수 순서)에서 수행됩니다. 이는 불량한 것으로, 백만 개의 항목 (예 : 1000x100x10 배열)은 평균 500,000 회 반복하여 바늘을 찾습니다. 다차원 배열의 구조를 변경하기로 결정하면 어떻게 될까요? 그리고 깊이가 100을 초과하면 PHP는 재귀 알고리즘을 시작합니다. 컴퓨터 과학은 다음과 같이 더 잘할 수 있습니다.
가능하면 항상 다차원 배열 대신 객체를 사용하십시오.
ArrayObject(
MyObject(something, something_else))
...
MyObject(something100, something_else100))
)
사용자 정의 비교기 인터페이스 및 기능을 적용하여 정렬하고 찾습니다.
interface Comparable {
public function compareTo(Comparable $o);
}
class MyObject implements Comparable {
public function compareTo(Comparable $o){
...
}
}
function myComp(Comparable $a, Comparable $b){
return $a->compareTo($b);
}
당신이 사용할 수있는 uasort()
당신이 분류하고이를 관리 할 수 있습니다 개체에 대한 자신의 컬렉션을 구현해야 모험을 좋아하는 경우, 사용자 정의 비교를 사용하는 (난 항상 최소한의 검색 기능을 포함하는 ArrayObject을 확장).
$arrayObj->uasort("myComp");
일단 정렬되면 (uasort는 O (n log n), 임의의 데이터를 얻는 것만 큼 낫습니다), 이진 검색은 O (log n) 시간에 연산을 수행 할 수 있습니다. 검색. 사용자 정의 비교기 이진 검색이 PHP에서 구현되지 않는다는 것을 알고있는 한 ( array_search()
속성이 아닌 객체 참조에서 작동하는 자연 순서 사용), 내가하는 것처럼 이것을 직접 구현해야합니다.
객체가 정렬 방식을 정의하므로 코드를 무한히 재활용 할 수 있으므로이 방법은 더 효율적이고 (더 이상 깊이는 없지만) 더 중요합니다 (인터페이스를 사용하여 비교 가능성을 적용한다고 가정). 훨씬 더 나은 =)
답변
해결책은 다음과 같습니다.
<?php
$students['e1003']['birthplace'] = ("Mandaluyong <br>");
$students['ter1003']['birthplace'] = ("San Juan <br>");
$students['fgg1003']['birthplace'] = ("Quezon City <br>");
$students['bdf1003']['birthplace'] = ("Manila <br>");
$key = array_search('Delata Jona', array_column($students, 'name'));
echo $key;
?>