PHP 다차원 배열 검색 (특정 값으로 키 찾기)


114

이 다차원 배열이 있습니다. 나는 그것을 검색하고 "슬러그"의 값과 일치하는 키만 반환해야합니다. 다차원 배열 검색에 대한 다른 스레드가 있다는 것을 알고 있지만 내 상황에 적용 할만큼 충분히 이해하지 못하고 있습니다. 도움을 주셔서 대단히 감사합니다!

그래서 다음과 같은 기능이 필요합니다.

myfunction($products,'breville-one-touch-tea-maker-BTM800XL');
// returns 1

다음은 어레이입니다.

$products = array (
1  => array(
        'name'          => 'The Breville One-Touch Tea Maker',
        'slug'          => 'breville-one-touch-tea-maker-BTM800XL',
        'shortname'     => 'The One-Touch Tea Maker',
        'listprice'     => '299.99',
        'price'         => '249.99',
        'rating'        => '9.5',
        'reviews'       => '81',
        'buyurl'        => 'http://www.amazon.com/The-Breville-One-Touch-Tea-Maker/dp/B003LNOPSG',
        'videoref1'     => 'xNb-FOTJY1c',
        'videoref2'     => 'WAyk-O2B6F8',
        'image'         => '812BpgHhjBML.jpg',
        'related1'      => '2',
        'related2'      => '3',
        'related3'      => '4',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => 'K. Martino',
        ),

2  => array(
        'name'          => 'Breville Variable-Temperature Kettle BKE820XL',
        'slug'          => 'breville-variable-temperature-kettle-BKE820XL',
        'shortname'     => 'Variable Temperature Kettle',
        'listprice'     => '199.99',
        'price'         => '129.99',
        'rating'        => '9',
        'reviews'       => '78',
        'buyurl'        => 'http://www.amazon.com/Breville-BKE820XL-Variable-Temperature-1-8-Liter-Kettle/dp/B001DYERBK',
        'videoref1'     => 'oyZWBD83xeE',
        'image'         => '41y2B8jSKmwL.jpg',
        'related1'      => '3',
        'related2'      => '4',
        'related3'      => '5',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => '',
        ),
);

답변:


157

매우 간단합니다.

function myfunction($products, $field, $value)
{
   foreach($products as $key => $product)
   {
      if ( $product[$field] === $value )
         return $key;
   }
   return false;
}

6
조건문에서이 함수를 사용하는 경우 반환 된 키의 인덱스가 [0] 일 수 있으므로 유형에 대해 절대 검사를 수행해야합니다. : 조건부 검사를 수행하는 경우, 그것은 다음과 비슷한 모습이 될 것입니다 그래서 if (myfunction($array, 'field', 'value') !== FALSE )) // do something...
앤디 쿡

159

또 다른 poossible 솔루션은 array_search()함수를 기반으로합니다 . 당신은 PHP 5.5.0 사용할 필요 이상.

$userdb=Array
(
(0) => Array
    (
        (uid) => '100',
        (name) => 'Sandra Shush',
        (url) => 'urlof100'
    ),

(1) => Array
    (
        (uid) => '5465',
        (name) => 'Stefanie Mcmohn',
        (pic_square) => 'urlof100'
    ),

(2) => Array
    (
        (uid) => '40489',
        (name) => 'Michael',
        (pic_square) => 'urlof40489'
    )
);

$key = array_search(40489, array_column($userdb, 'uid'));

echo ("The key is: ".$key);
//This will output- The key is: 2

설명

이 함수 array_search()에는 두 개의 인수가 있습니다. 첫 번째는 검색하려는 값입니다. 두 번째는 함수가 검색해야하는 곳입니다. 이 함수 array_column()는 키가 인 요소의 값을 가져옵니다 'uid'.

요약

따라서 다음과 같이 사용할 수 있습니다.

array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));

또는 원하는 경우 :

// define function
function array_search_multidim($array, $column, $key){
    return (array_search($key, array_column($array, $column)));
}

// use it
array_search_multidim($products, 'slug', 'breville-one-touch-tea-maker-BTM800XL');

원본 예제 (xfoxawy 작성)는 DOCS 에서 찾을 수 있습니다 . 페이지 .
array_column()


최신 정보

Vael의 댓글로 궁금한 점이있어서 사용하는 방법의 성능 array_search과 수용된 답변에서 제안한 방법을 측정하기 위해 간단한 테스트를했습니다 .

1000 개의 배열을 포함하는 배열을 만들었는데, 구조는 다음과 같았습니다 (모든 데이터가 무작위 화됨).

[
      {
            "_id": "57fe684fb22a07039b3f196c",
            "index": 0,
            "guid": "98dd3515-3f1e-4b89-8bb9-103b0d67e613",
            "isActive": true,
            "balance": "$2,372.04",
            "picture": "http://placehold.it/32x32",
            "age": 21,
            "eyeColor": "blue",
            "name": "Green",
            "company": "MIXERS"
      },...
]

이름 필드에 대해 서로 다른 값을 검색하여 검색 테스트를 100 번 실행 한 다음 평균 시간 ( 밀리 초)을 계산했습니다 . 여기 에서 예를 볼 수 있습니다.

그 결과이 답변에서 제안한 방법은 값을 찾기 위해 약 2E-7이 필요하고, 수락 된 답변 방법은 약 8E-7이 필요했습니다.

이전에 말했듯이이 크기의 배열을 사용하는 응용 프로그램에서는 두 시간이 상당히 허용됩니다. 크기가 많이 커지면 1M 요소라고 가정하면이 작은 차이도 증가합니다.

업데이트 II

array_walk_recursive여기에 일부 답변에 대한 언급이 있었던 방법에 대한 테스트를 추가했습니다 . 얻은 결과는 올바른 것입니다. 그리고 우리가 성능에 초점을 맞추면 테스트에서 조사한 다른 것보다 약간 나쁩니다 . 테스트에서 .NET 기반 방법보다 약 10 배 느린 것을 확인할 수 있습니다 array_search. 다시 말하지만, 이것은 대부분의 응용 프로그램에서 그다지 적절한 차이가 아닙니다.

업데이트 III

이 방법에 대한 몇 가지 제한 사항을 발견 한 @mickmackusa에게 감사드립니다.

  • 이 방법은 연관 키에서 실패합니다.
  • 이 메서드는 인덱스 된 하위 배열에서만 작동합니다 (0부터 시작하고 연속적으로 오름차순 키를 가짐).

누구든지 이것의 성능을 알고 있습니까? 궁극적으로 더 느려질 것 같지만 여전히 5.5가 필요합니다. 5.4에서 테스트 할 수 없습니다.
Vael Victus 2016 년

이해하지 못하는 사람은 PHP 7에서 for 루프가 더 빠릅니다. 이 eval.in 예제에서 5.6으로 변경했을 때 array_search가 약간 더 빨랐습니다.
Vael Victus 2016

영리한! 알려진 키로 데이터를 가져올 다른 배열을 만들기 위해 array_column ()과 함께 array_combine ()을 사용하여 비슷한 작업을 수행했지만 이것은 더 우아합니다.
David

4
array_search()with array_column()를 사용 하면 하위 배열 키가에서 시작하기 때문에 OP의 샘플 배열에서 작동하지 않습니다 1. 이 방법은 연관 키에서도 실패합니다. 이 메서드는 인덱스 된 하위 배열에서만 작동합니다 ( 0연속 오름차순 키 에서 시작 하고 포함). 그 이유 array_column()는 반환 된 배열에 새 인덱스를 생성 하기 때문 입니다.
mickmackusa

@mickmackusa가 완전히 맞습니다. 답변에 귀하의 지식을 추가했습니다. 도움을 주셔서 감사합니다
이반 로드리게스 토레스

14

이 클래스 메서드는 여러 조건으로 배열에서 검색 할 수 있습니다.

class Stdlib_Array
{
    public static function multiSearch(array $array, array $pairs)
    {
        $found = array();
        foreach ($array as $aKey => $aVal) {
            $coincidences = 0;
            foreach ($pairs as $pKey => $pVal) {
                if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) {
                    $coincidences++;
                }
            }
            if ($coincidences == count($pairs)) {
                $found[$aKey] = $aVal;
            }
        }

        return $found;
    }    
}

// Example:

$data = array(
    array('foo' => 'test4', 'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test1', 'bar' => 'baz3'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz4'),
    array('foo' => 'test4', 'bar' => 'baz1'),
    array('foo' => 'test',  'bar' => 'baz1'),
    array('foo' => 'test3', 'bar' => 'baz2'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test4', 'bar' => 'baz1')
);

$result = Stdlib_Array::multiSearch($data, array('foo' => 'test4', 'bar' => 'baz1'));

var_dump($result);

다음을 생성합니다.

array(2) {
  [5]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
  [10]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
}

안녕하세요 숙명 론자 stackoverflow.com/questions/40860030/... . 당신이 그 질문을 명확히하시기 바랍니다 수있는 이러한 질문에 releted한다
카디 SRV를

4

이 기능을 사용하십시오 :

function searchThroughArray($search,array $lists){
        try{
            foreach ($lists as $key => $value) {
                if(is_array($value)){
                    array_walk_recursive($value, function($v, $k) use($search ,$key,$value,&$val){
                        if(strpos($v, $search) !== false )  $val[$key]=$value;
                    });
            }else{
                    if(strpos($value, $search) !== false )  $val[$key]=$value;
                }

            }
            return $val;

        }catch (Exception $e) {
            return false;
        }
    }

및 호출 기능.

print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));

좋은 대답입니다. 당신은 내 대답에 제안의 성능을 확인할 수 있습니다
이반 로드리게스 토레스에게

코드 전용 답변은 StackOverflow에서 낮은 가치입니다. 리프 노드 하위 문자열 검색 기능이 작동하는 방식을 설명하기 위해 게시물을 업데이트하십시오. 이 방법은 OP가 요구하는대로 작동하도록 특별히 설계되지 않았으므로 차이점을 명확히하는 것이 중요합니다. 데모 링크는 독자의 이해도를 크게 향상시킵니다. 항상 OP와 더 많은 청중을 교육하려는 의도로 답변을 게시하십시오.
mickmackusa

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; 
} 

코드 전용 답변은 StackOverflow에서 낮은 가치입니다. 재귀 적 방법의 작동 방식, 적절한 상황, 재귀가 불필요한 오버 헤드 상황을 설명하도록 게시물을 업데이트하십시오. 항상 OP와 더 많은 청중을 교육하려는 의도로 답변을 게시하십시오.
mickmackusa

1

다음 방문자를 위해 : 재귀 배열 워크를 사용하십시오. 다차원 배열의 모든 "잎"을 방문합니다. 영감을 얻으려면 :

function getMDArrayValueByKey($a, $k) {
    $r = [];
    array_walk_recursive ($a, 
                          function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
                          );
    return $r;
}

문제 없어요! 시간을 절약하기 위해 josef 대답을 시도하면 함수는 하나의 요소가있는 배열을 반환합니다. 핵심은 : 원하는 답변입니다
이반 로드리게스 토레스

@Ivan josef의 대답은 이것과 매우 다릅니다. 직접 테스트 했습니까? 나는이 대답을 계속 주시하고 array_walk_recursive가 수준을 볼 수 없기 때문에 작동하지 않는다고 생각합니다. 각 첫 번째 수준 키에 대해 josef는 strpos를 호출하거나 모든 리프 노드를 확인합니다. 차이점이 보이십니까?
mickmackusa

물론 @mickmackusa 그러나 Hans는 어떤 종류의 영감을주고 있습니다. 대답은 말 그대로 해결책을 제공하는 것이 아닙니다. Josef가 대답 한 것처럼 더 많은 정교함이 필요합니다. 그러나이 답변이 문제를 완전히 해결하지 못한다는 점에서 맞습니다.
Iván Rodríguez Torres

1

나는 $products맨 처음에 문제에 주어진 실제 배열이 어디에 있습니까 ?

print_r(
  array_search("breville-variable-temperature-kettle-BKE820XL", 
  array_map(function($product){return $product["slug"];},$products))
);

0

이 시도

function recursive_array_search($needle,$haystack) {
        foreach($haystack as $key=>$value) {
            $current_key=$key;
            if($needle==$value['uid'] OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
                return $current_key;
            }
        }
        return false;
    }

코드 전용 답변은 StackOverflow에서 낮은 가치입니다. 재귀 적 방법의 작동 방식, 적절한 상황, 재귀가 불필요한 오버 헤드 상황을 설명하도록 게시물을 업데이트하십시오. 항상 OP와 더 많은 청중을 교육하려는 의도로 답변을 게시하십시오. 시 나는 대부분의 PHP 개발자가 선호하는 것이라고 생각 &&하고 ||대신 AND하고 OR당신의 상태에. 선언 할 이유가 없습니다 current_key. 에 대한 비교 $needle는 엄격해야합니다.
mickmackusa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.