PHP में बहुआयामी सरणी में कुंजी => मान से कैसे खोज करें


147

क्या सभी उपग्रहों को प्राप्त करने का कोई तेज़ तरीका है जहां एक महत्वपूर्ण मूल्य जोड़ी एक बहुआयामी सरणी में पाई गई थी? मैं नहीं कह सकता कि सरणी कितनी गहरी होगी।

सरल उदाहरण सरणी:

$arr = array(0 => array(id=>1,name=>"cat 1"),
             1 => array(id=>2,name=>"cat 2"),
             2 => array(id=>3,name=>"cat 1")
);

जब मैं कुंजी = नाम और मान = "कैट 1" खोजता हूं, तो फ़ंक्शन को वापस आ जाना चाहिए:

array(0 => array(id=>1,name=>"cat 1"),
      1 => array(id=>3,name=>"cat 1")
);

मुझे लगता है कि समारोह को सबसे गहरे स्तर तक ले जाने के लिए पुनरावर्ती होना चाहिए।

जवाबों:


217

कोड:

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)


2
@JohnKugelman यदि $keyसरणी में मौजूद नहीं है, तो "कुशल" उत्तर त्रुटि न करें? ऐसा करना बेहतर नहीं होगा if (array_key_exists($key, $array) && $array[$key] == $value) {?
चेस

1
@JohnKugelman यह फ़ंक्शन अच्छा काम करता है, लेकिन कभी-कभी मेरे पास मेरा काम $valueहोता है nullऔर यह फ़ंक्शन काम नहीं करता है ... array empty... एक सरणी कैसे भी हो सकती है $value= null? पसंद है search($array, 'id', null)?
झग्लू

71

इसके बजाय 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 का उपयोग करके, आपके लिए एक निर्देशिका के माध्यम से पुनरावृत्ति करेगा। एसपीएल रॉक्सर है।

एसपीएल के बारे में एकमात्र बुमेर यह है कि यह वेब पर बुरी तरह से प्रलेखित है। लेकिन कई PHP किताबें कुछ उपयोगी विवरण में जाती हैं, विशेष रूप से प्रो PHP; और आप शायद अधिक जानकारी के लिए भी google कर सकते हैं।


यह एक आकर्षण की तरह काम करता है और मैं इसी तरह की समस्याओं के लिए इसे फिर से उपयोग करने की योजना बनाता हूं: डी केवल अजीब हिस्सा फॉर्च्यूनर में है और $ उप चर के बजाय RecursiveIteratorIterator पर getSubIterator फ़ंक्शन का उपयोग कर रहा है। मैंने सोचा था कि यह पहली बार एक टाइपो था, लेकिन यह सही तरीका है! धन्यवाद जेरेड।
बछन

2
बहुत बढ़िया समाधान। बहुत तेज!
टेलरऑटवेल

समाधान के लिए धन्यवाद। हम "आईडी" कहाँ प्राप्त करते हैं? $ OutputArray से?
ट्रांटे

धन्यवाद, बहुत सीधे आगे समाधान, लेकिन प्रदर्शन के बारे में पता नहीं है ??
महेश.दिसंबर 14'13

मूल सरणी से पाया गया तत्व (एक उप-सरणी) कैसे हो सकता है?
Fr0zenFyr

49
<?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);

?>

Ref: http://php.net/manual/en/function.array-filter.php


4
यह एक अच्छा समाधान है यदि आप किसी ऐसे सरणी को खोजना चाहते हैं जो केवल एक स्तर गहरा है, लेकिन यह विशेष प्रश्न एक गहरी सरणी में पुनरावर्ती खोज के बारे में था ("फ़ंक्शन को सबसे गहरे स्तर तक नीचे जाने के लिए पुनरावर्ती होना चाहिए")।
orrd

16

इन उत्तरों पर अनुकूलन टिप की आवश्यकता वाले किसी भी व्यक्ति के लिए इस अपडेट को पोस्ट करने के लिए वापस आया, पार्टिसिपलरी जॉन कुगेलमैन के महान जवाब ऊपर।

उनकी पोस्ट की गई फ़ंक्शन ठीक है लेकिन मुझे 12 000 पंक्ति परिणाम को संभालने के लिए इस परिदृश्य को अनुकूलित करना पड़ा। यह फंक्शन सभी रिकॉर्ड्स से गुजरने के लिए शाश्वत 8 सेकेंड का समय ले रहा था।

मुझे बस इस बात की ज़रूरत थी कि जब मैच मिल जाए, तो STOP खोजे और वापस लौटे। यानी, अगर हम 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;       
    } 
}

इसने १२ ००० रिकॉर्ड को १.५ सेकंड तक मिलान करने के लिए कार्य को नीचे लाया। अभी भी बहुत महंगा है, लेकिन बहुत अधिक उचित है।


यह झोन / जारेड के उत्तर (0.0009999275207519) बनाम (0.0020008087158203) से अधिक तेज़ है। खैर यह परीक्षण मेरे मामले और वातावरण के लिए विशिष्ट है। Im इसके साथ चिपका, धन्यवाद स्टेफेलिन
Awena

14
if (isset($array[$key]) && $array[$key] == $value)

तेजी से संस्करण के लिए एक मामूली हानि।


2
वास्तव में यह कुंजी सेट नहीं होने पर चेतावनी को फेंकने से रोकता है। इतना मामूली नहीं! -> + 1'द।
स्टेफगॉसलिन

2
सहमत, वास्तव में प्रमुख त्रुटियों के लिए php त्रुटि लॉग के माध्यम से नज़र रखने में सक्षम होने और चेतावनी के साथ प्रदूषित नहीं होने के कारण मेरी राय में जाने का तरीका है।
कोडरके

यह एक पूर्ण समाधान नहीं है और इसलिए "एक अन्य पोस्ट पर जवाब देने का प्रयास" और "एक उत्तर नहीं" का अधिक है।
मिकमेकुसा

7

कई आयामी सरणियों में रैखिक खोज एल्गोरिदम (उपरोक्त रैखिक हैं) से सावधान रहें क्योंकि उनके पास जटिल जटिलता है क्योंकि इसकी गहराई पूरे सरणी को पार करने के लिए आवश्यक पुनरावृत्तियों की संख्या को बढ़ाती है। उदाहरण के लिए:

array(
    [0] => array ([0] => something, [1] => something_else))
    ...
    [100] => array ([0] => something100, [1] => something_else100))
)

एक उपयुक्त एल्गोरिथ्म के साथ (यदि सुई [100] [1] पर थी), तो आप जो ढूंढ रहे हैं, उसे खोजने के लिए सबसे अधिक 200 पुनरावृत्तियों पर ध्यान देना होगा।

इस मामले में रैखिक एल्गोरिदम ओ (एन) पर प्रदर्शन करते हैं (पूरे सरणी में तत्वों की कुल संख्या), यह खराब है, एक लाख प्रविष्टियां (उदाहरण के लिए एक 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 लॉग एन), जो कि मनमाने ढंग से डेटा मिलने पर उतना ही अच्छा होता है), बाइनरी सर्च ओ (लॉग एन) समय में ऑपरेशन कर सकता है, यानी एक मिलियन एंट्रीज़ में केवल ~ 20 पुनरावृत्तियों को लेना है खोज। जहाँ तक मुझे पता है कि कस्टम तुलनित्र बाइनरी खोज PHP में लागू नहीं है (array_search() प्राकृतिक ऑर्डरिंग का उपयोग करता है जो ऑब्जेक्ट के संदर्भ में काम करता है न कि उनके गुण), आपको इसे अपने स्वयं को लागू करना होगा जैसे मैं करता हूं।

यह दृष्टिकोण अधिक कुशल है (अब कोई गहराई नहीं है) और अधिक महत्वपूर्ण रूप से सार्वभौमिक (मान लेते हैं कि आप इंटरफेस का उपयोग करते हुए तुलनीयता लागू करते हैं) क्योंकि ऑब्जेक्ट परिभाषित करते हैं कि वे कैसे सॉर्ट किए जाते हैं, इसलिए आप कोड को असीम रूप से पुन: चक्रित कर सकते हैं। बहुत बेहतर =)


यह उत्तर सही होना चाहिए। हालांकि जानवर बल खोज विधि यह करेंगे, यह बहुत कम संसाधन गहन है।
ड्रयू

यह ध्यान दिया जाना चाहिए कि आप जो सुझाव दे रहे हैं वह केवल तभी समझ में आता है जब आप एक ही सरणी को कई बार खोज रहे हों। इसे छांटने में (O (n log n)) की परेशानी से गुजरने में अधिक समय लगता है, क्योंकि यह केवल मान (O (n)) के लिए एक रेखीय खोज करता है। लेकिन एक बार जब यह हल हो जाता है, तो निश्चित रूप से, फिर एक द्विआधारी खोज तेजी से होगी।
orrd

मुझे यह भी जोड़ना चाहिए कि सरणियों के बजाय वस्तुओं का उपयोग करना एक उपयोगी अमूर्तता हो सकती है, लेकिन आप सरणी को क्रमबद्ध करने पर सरणी पर एक द्विआधारी खोज भी कर सकते हैं। आपको किसी सरणी को सॉर्ट करने या उस पर एक बाइनरी खोज करने के लिए वस्तुओं का उपयोग करने की आवश्यकता नहीं है।
orrd

6

यहाँ समाधान है:

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

?>


3

http://snipplr.com/view/51108/nested-array-search-by-value-or-key/

<?php

//PHP 5.3

function searchNestedArray(array $array, $search, $mode = 'value') {

    foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key => $value) {
        if ($search === ${${"mode"}})
            return true;
    }
    return false;
}

$data = array(
    array('abc', 'ddd'),
    'ccc',
    'bbb',
    array('aaa', array('yyy', 'mp' => 555))
);

var_dump(searchNestedArray($data, 555));

3
function in_multi_array($needle, $key, $haystack) 
{
    $in_multi_array = false;
    if (in_array($needle, $haystack))
    {
        $in_multi_array = true; 
    }else 
    {
       foreach( $haystack as $key1 => $val )
       {
           if(is_array($val)) 
           {
               if($this->in_multi_array($needle, $key, $val)) 
               {
                   $in_multi_array = true;
                   break;
               }
           }
        }
    }

    return $in_multi_array;
} 

मेरा मामला अलग है लेकिन आपके जवाब से संकेत मिल गया है।
shyammakwana.me

2

मुझे कुछ इसी तरह की जरूरत थी, लेकिन मूल्य द्वारा बहुआयामी सरणी की खोज करने के लिए ... मैंने जॉन का उदाहरण लिया और लिखा

function _search_array_by_value($array, $value) {
        $results = array();
        if (is_array($array)) {
            $found = array_search($value,$array);
            if ($found) {
                $results[] = $found;
            }
            foreach ($array as $subarray)
                $results = array_merge($results, $this->_search_array_by_value($subarray, $value));
        }
        return $results;
    }

मुझे आशा है कि यह किसी की मदद करता है :)


2

यह जॉन के द्वारा पोस्ट की गई एक संशोधित फ़ंक्शन है ... मुझे सरणी में केवल विशिष्ट कुंजी को हथियाने की जरूरत है और इसके ऊपर कुछ भी नहीं है।

function search_array ( $array, $key, $value )
{
    $results = array();

    if ( is_array($array) )
    {
        if ( $array[$key] == $value )
        {
            $results[] = $array;
        } else {
            foreach ($array as $subarray) 
                $results = array_merge( $results, $this->search_array($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_array($arr, 'name', 'cat 1'));

1

और एक अन्य संस्करण जो सरणी तत्व से महत्वपूर्ण मान लौटाता है जिसमें मूल्य पाया जाता है (गति के लिए अनुकूलित नहीं पुनरावृत्ति):

// if the array is 
$arr['apples'] = array('id' => 1);
$arr['oranges'] = array('id' => 2);

//then 
print_r(search_array($arr, 'id', 2);
// returns Array ( [oranges] => Array ( [id] => 2 ) ) 
// instead of Array ( [0] => Array ( [id] => 2 ) )

// search array for specific key = value
function search_array($array, $key, $value) {
  $return = array();   
  foreach ($array as $k=>$subarray){  
    if (isset($subarray[$key]) && $subarray[$key] == $value) {
      $return[$k] = $subarray;
      return $return;
    } 
  }
}

यहां पोस्ट करने वाले सभी का धन्यवाद।


1
function findKey($tab, $key){
    foreach($tab as $k => $value){ 
        if($k==$key) return $value; 
        if(is_array($value)){ 
            $find = findKey($value, $key);
            if($find) return $find;
        }
    }
    return null;
}

2
क्या आप इस उत्तर पर विस्तार कर सकते हैं? कोड केवल उत्तर बताते हैं कि आप वास्तव में क्या कर रहे हैं।
रिच बेननर

कृपया अपने प्रश्न को शिक्षित करने के इरादे से अपडेट करें।
मिकमैकुसा

यह केवल कुंजी खोजने के लिए कार्यात्मक है, यह मेरे लिए काम करता है।
गियोवन्नी गोंजालेज

0

यदि आप चाबियों की तलाश करना चाहते हैं तो यह अच्छा है

function searchKeysInMultiDimensionalArray($array, $keys)
{
    $results = array();

    if (is_array($array)) {
        $resultArray = array_intersect_key($array, array_flip($keys));
        if (!empty($resultArray)) {
            $results[] = $resultArray;
        }

        foreach ($array as $subarray) {
            $results = array_merge($results, searchKeysInMultiDimensionalArray($subarray, $keys));
        }
    }

    return $results;
}

कुंजी अधिलेखित नहीं होगी क्योंकि कुंजी के प्रत्येक सेट => मान परिणामी सरणी में अलग सरणी में होंगे।
यदि आप डुप्लिकेट कुंजी नहीं चाहते हैं तो इस का उपयोग करें

function searchKeysInMultiDimensionalArray($array, $keys)
{
    $results = array();

    if (is_array($array)) {
        $resultArray = array_intersect_key($array, array_flip($keys));
        if (!empty($resultArray)) {
            foreach($resultArray as $key => $single) {

                $results[$key] = $single;
            }
        }

        foreach ($array as $subarray) {
            $results = array_merge($results, searchKeysInMultiDimensionalArray($subarray, $keys));
        }
    }

    return $results;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.