PHP: सरणी कुंजियों को फ़िल्टर करने के लिए array_filter () का उपयोग कैसे करें?


363

कॉलबैक फ़ंक्शन array_filter()केवल सरणी के मूल्यों में गुजरता है, चाबियाँ नहीं।

अगर मेरे पास:

$my_array = array("foo" => 1, "hello" => "world");

$allowed = array("foo", "bar");

$my_arrayउस $allowedसरणी में सभी कुंजियों को हटाने का सबसे अच्छा तरीका क्या है ?

वांछित उत्पादन:

$my_array = array("foo" => 1);

नहीं एक समाधान है, लेकिन एक और दृष्टिकोण है कि उपयोगी हो सकता है करने के लिए है $b = ['foo' => $a['foo'], 'bar' => $a['bar']]में परिणाम होगा यह $b['bar']हो null
ओरिदम

जवाबों:


322

पीएचपी 5.6 एक तिहाई पैरामीटर के लिए शुरू की array_filter(), flagहै, तो आप करने के लिए सेट कर सकते हैं कि ARRAY_FILTER_USE_KEYमान के बजाय कुंजी द्वारा फिल्टर करने के लिए:

$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed  = ['foo', 'bar'];
$filtered = array_filter(
    $my_array,
    function ($key) use ($allowed) {
        return in_array($key, $allowed);
    },
    ARRAY_FILTER_USE_KEY
);

स्पष्ट रूप से यह उतना सुरुचिपूर्ण नहीं है array_intersect_key($my_array, array_flip($allowed)), लेकिन यह कुंजी के खिलाफ एक मनमाना परीक्षण करने के अतिरिक्त लचीलेपन की पेशकश करता है, जैसे $allowedकि सादे तार के बजाय रेगेक्स पैटर्न हो सकते हैं।

आप ARRAY_FILTER_USE_BOTHअपने फ़िल्टर फ़ंक्शन के लिए दिए गए मान और कुंजी दोनों का उपयोग कर सकते हैं । यहाँ पहले के आधार पर एक वंचित उदाहरण दिया गया है, लेकिन ध्यान दें कि मैं $allowedइस तरह से उपयोग करने वाले फ़िल्टरिंग नियमों को एन्कोडिंग करने की सलाह नहीं दूंगा :

$my_array = ['foo' => 1, 'bar' => 'baz', 'hello' => 'wld'];
$allowed  = ['foo' => true, 'bar' => true, 'hello' => 'world'];
$filtered = array_filter(
    $my_array,
    function ($val, $key) use ($allowed) { // N.b. $val, $key not $key, $val
        return isset($allowed[$key]) && (
            $allowed[$key] === true || $allowed[$key] === $val
        );
    },
    ARRAY_FILTER_USE_BOTH
); // ['foo' => 1, 'bar' => 'baz']

21
धिक्कार है, उस विशेषता के लेखक के रूप में मुझे इस प्रश्न की तलाश करनी चाहिए
;; ͢

1
धन्यवाद, यह बेहतर हैarray_intersect
brzuchal

461

के साथ array_intersect_keyऔर array_flip:

var_dump(array_intersect_key($my_array, array_flip($allowed)));

array(1) {
  ["foo"]=>
  int(1)
}

1
मैं उत्सुक हूँ अगर यह मेरे समाधान से अधिक कुशल है, हालांकि? यह निश्चित रूप से अधिक सुंदर है :)
GWW

13
यह एक सामान्य समाधान नहीं है क्योंकि यह अनिवार्य होगा कि प्रत्येक मूल्य अद्वितीय हो। संपादित करें: क्षमा करें .. मैं समाधान गलत। अनुमत कुंजियों पर फ़्लिप करना एक अच्छा समाधान (+1) है
मैथ्यू

@GWW: मुझे नहीं पता कि यह अधिक कुशल है, टीबीएच। @konforce: मुझे आपकी बात समझ में नहीं आ रही है। किसी सरणी में दो समान कुंजियाँ नहीं हो सकती हैं, इसलिए यह केवल $ my_array में चाबियाँ लौटाएगी जो $ अनुमति में मौजूद हैं।
विंसेंट सवार्ड

1
या बस ARRAY_FILTER_USE_KEY का उपयोग करें: P
जूलियन पैलार्ड

1
क्यों उपयोग करें array_flip? बस $allowedचाबियों के साथ परिभाषित करें:allowed = array ( 'foo' => 1, 'bar' => 1 );
युवल ए।

43

मुझे वही करने की ज़रूरत थी, लेकिन array_filterचाबियों पर अधिक जटिल के साथ ।

यहां मैंने एक समान विधि का उपयोग करके यह कैसे किया।

// Filter out array elements with keys shorter than 4 characters
$a = array(
  0      => "val 0", 
  "one"  => "val one", 
  "two"  => "val two", 
  "three"=> "val three", 
  "four" => "val four", 
  "five" => "val five", 
  "6"    => "val 6"
); 

$f = array_filter(array_keys($a), function ($k){ return strlen($k)>=4; }); 
$b = array_intersect_key($a, array_flip($f));
print_r($b);

यह परिणाम का परिणाम है:

Array
(
    [three] => val three
    [four] => val four
    [five] => val five
)

8

यहां एक क्लोजर का उपयोग करके अधिक लचीला समाधान है:

$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$result = array_flip(array_filter(array_flip($my_array), function ($key) use ($allowed)
{
    return in_array($key, $allowed);
}));
var_dump($result);

आउटपुट:

array(1) {
  'foo' =>
  int(1)
}

तो फ़ंक्शन में, आप अन्य विशिष्ट परीक्षण कर सकते हैं।


1
मैं इसे "अधिक लचीला" नहीं कहूंगा; यह स्वीकृत समाधान की तुलना में बहुत कम सीधा लगता है।
माकक

मैं सहमत हूँ। यह अधिक लचीला होगा स्थिति एक अधिक जटिल थी।
कोइल

1
अन्य उपयोगकर्ताओं के लिए बस पास होने से: यह समाधान इस मामले से नहीं निपटता है कि $ my_array में डुप्लिकेट मान या मान हैं जो पूर्णांक या तार नहीं हैं। इसलिए मैं इस समाधान का उपयोग नहीं करूंगा।
user23127

2
मैं मानता हूं कि यह अधिक लचीला है क्योंकि यह आपको फ़िल्टर तर्क को बदलने की अनुमति देता है। उदाहरण के लिए, मैंने नापसंद कुंजियों की एक सरणी का उपयोग किया और बस वापस लौट आया! (In_array ($ कुंजी, $ अस्वीकृत)।
nfplee

5

यदि आप कुंजियों में होने वाली स्ट्रिंग द्वारा किसी सरणी को फ़िल्टर करने के लिए एक विधि की तलाश कर रहे हैं, तो आप उपयोग कर सकते हैं:

$mArray=array('foo'=>'bar','foo2'=>'bar2','fooToo'=>'bar3','baz'=>'nope');
$mSearch='foo';
$allowed=array_filter(
    array_keys($mArray),
    function($key) use ($mSearch){
        return stristr($key,$mSearch);
    });
$mResult=array_intersect_key($mArray,array_flip($allowed));

का परिणाम print_r($mResult)है

Array ( [foo] => bar [foo2] => bar2 [fooToo] => bar3 )

इस उत्तर का एक अनुकूलन जो नियमित अभिव्यक्तियों का समर्थन करता है

function array_preg_filter_keys($arr, $regexp) {
  $keys = array_keys($arr);
  $match = array_filter($keys, function($k) use($regexp) {
    return preg_match($regexp, $k) === 1;
  });
  return array_intersect_key($arr, array_flip($match));
}

$mArray = array('foo'=>'yes', 'foo2'=>'yes', 'FooToo'=>'yes', 'baz'=>'nope');

print_r(array_preg_filter_keys($mArray, "/^foo/i"));

उत्पादन

Array
(
    [foo] => yes
    [foo2] => yes
    [FooToo] => yes
)

आपके उत्तर के लिए धन्यवाद। मैं आपको प्रस्तुत करूंगा कि stristrफ़ंक्शन के "काम" के भीतर उपयोग करना अंतिम उपयोगकर्ता के लिए कुछ धारणाएं बना रहा है। शायद उपयोगकर्ता को नियमित अभिव्यक्ति में पारित करने की अनुमति देना बेहतर होगा; इससे उन्हें एंकर, शब्द सीमा और केस सेंसिटिविटी इत्यादि जैसी कुछ चीजों पर अधिक लचीलापन
मिलेगा

मैंने आपके उत्तर का एक रूपांतरण जोड़ा है जो अन्य लोगों की मदद कर सकता है
20

1
आप निश्चित रूप से सही हैं, maček, यह उन उपयोगकर्ताओं के लिए अधिक बहुमुखी दृष्टिकोण है जो रेगेक्स के साथ सहज हैं। धन्यवाद।
निकोलस जिमर

5

उपयोग करते समय किसी सरणी की वर्तमान कुंजी कैसे प्राप्त करें array_filter

भले ही मैं Maček की समस्या के लिए विन्सेंट के समाधान को कैसे पसंद करता हूं, यह वास्तव में उपयोग नहीं करता है array_filter। यदि आप एक खोज इंजन से यहां आए हैं, तो आप शायद इस तरह से कुछ खोज रहे हैं ( PHP> = 5.3 ):

$array = ['apple' => 'red', 'pear' => 'green'];
reset($array); // Unimportant here, but make sure your array is reset

$apples = array_filter($array, function($color) use ($&array) {
  $key = key($array);
  next($array); // advance array pointer

  return key($array) === 'apple';
}

यह उस सरणी को पास करता है जिसे आप कॉलबैक के संदर्भ में फ़िल्टर कर रहे हैं। जैसा कि array_filterपारंपरिक रूप से यह आपके द्वारा इसे आगे बढ़ाना है सार्वजनिक आंतरिक सूचक को बढ़ाकर सरणी पर पारंपरिक रूप से पुनरावृति नहीं करता है।

यहां जो महत्वपूर्ण है वह यह है कि आपको यह सुनिश्चित करने की आवश्यकता है कि आपका सरणी रीसेट हो, अन्यथा आप इसके ठीक बीच में शुरू कर सकते हैं।

में पीएचपी> = 5.4 आप कॉलबैक भी कम कर सकता है:

$apples = array_filter($array, function($color) use ($&array) {
  return each($array)['key'] === 'apple';
}

3

यहाँ एक कम लचीले विकल्प का उपयोग कर परेशान है () :

$array = array(
    1 => 'one',
    2 => 'two',
    3 => 'three'
);
$disallowed = array(1,3);
foreach($disallowed as $key){
    unset($array[$key]);
}

होने का परिणाम print_r($array):

Array
(
    [2] => two
)

यह लागू नहीं है यदि आप फ़िल्टर किए गए मानों को बाद में उपयोग करने के लिए रखना चाहते हैं लेकिन टिडियर, यदि आप निश्चित हैं कि आप नहीं करते हैं।


1
आपको यह जाँचना चाहिए कि क्या कुंजी में $ $ कुंजी मौजूद नहीं है।
जारेक जकुबोव्स्की

3
@JarekJakubowski आपको यह जांचने की आवश्यकता नहीं है कि उपयोग करते समय एक सरणी कुंजी मौजूद है या नहीं unset()। यदि कुंजी मौजूद नहीं है तो कोई चेतावनी जारी नहीं की जाती है।
क्रिस्टोफर

3

PHP 5.6 से शुरू होकर, आप इस ARRAY_FILTER_USE_KEYझंडे का उपयोग कर सकते हैं array_filter:

$result = array_filter($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
}, ARRAY_FILTER_USE_KEY);


अन्यथा, आप इस फ़ंक्शन ( TestDummy से ) का उपयोग कर सकते हैं :

function filter_array_keys(array $array, $callback)
{
    $matchedKeys = array_filter(array_keys($array), $callback);

    return array_intersect_key($array, array_flip($matchedKeys));
}

$result = filter_array_keys($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
});


और यहाँ मेरा एक संवर्धित संस्करण है, जो कॉलबैक या सीधे कुंजी स्वीकार करता है:

function filter_array_keys(array $array, $keys)
{
    if (is_callable($keys)) {
        $keys = array_filter(array_keys($array), $keys);
    }

    return array_intersect_key($array, array_flip($keys));
}

// using a callback, like array_filter:
$result = filter_array_keys($my_array, function ($k) use ($allowed) {
    return in_array($k, $allowed);
});

// or, if you already have the keys:
$result = filter_array_keys($my_array, $allowed));


अंतिम लेकिन कम से कम, आप एक साधारण का उपयोग भी कर सकते हैं foreach:

$result = [];
foreach ($my_array as $key => $value) {
    if (in_array($key, $allowed)) {
        $result[$key] = $value;
    }
}

1

शायद एक ओवरकिल अगर आपको इसकी जरूरत सिर्फ एक बार है, लेकिन आप संग्रह को फ़िल्टर करने के लिए * यालिंको लाइब्रेरी * का उपयोग कर सकते हैं (और कोई अन्य परिवर्तन कर सकते हैं)। यह लाइब्रेरी ऑब्जेक्ट को धाराप्रवाह सिंटैक्स के साथ SQL- तरह के प्रश्नों को बेहतर बनाने की अनुमति देती है। इसका whereकार्य दो तर्कों के साथ एक कैलबैक स्वीकार करता है: एक मूल्य और एक कुंजी। उदाहरण के लिए:

$filtered = from($array)
    ->where(function ($v, $k) use ($allowed) {
        return in_array($k, $allowed);
    })
    ->toArray();

( whereफ़ंक्शन एक पुनरावृत्ति देता है, इसलिए यदि आपको केवल foreachएक बार परिणामी अनुक्रम के साथ पुनरावृति करने की आवश्यकता है, तो ->toArray()हटाया जा सकता है।)

* मेरे द्वारा विकसित


1

php से सरणी फ़िल्टर फ़ंक्शन:

array_filter ( $array, $callback_function, $flag )

$ अरै - यह इनपुट ऐरे है

$ कॉलबैक_फंक्शन - कॉलबैक फ़ंक्शन का उपयोग करने के लिए call यदि कॉलबैक फ़ंक्शन सही है , तो सरणी से वर्तमान मान परिणाम सरणी में वापस आ जाता है।

$ ध्वज - यह वैकल्पिक पैरामीटर है , यह निर्धारित करेगा कि कॉलबैक फ़ंक्शन पर क्या तर्क भेजे जाते हैं। यदि यह पैरामीटर खाली है तो कॉलबैक फ़ंक्शन तर्क मानों को तर्क के रूप में ले जाएगा। यदि आप तर्क के रूप में सरणी कुंजी भेजना चाहते हैं तो ARRAY_FILTER_USE_KEY के रूप में $ ध्वज का उपयोग करें । यदि आप कुंजी और मान दोनों भेजना चाहते हैं, तो आपको ARRAY_FILTER_USE_BOTH के रूप में $ ध्वज का उपयोग करना चाहिए ।

उदाहरण के लिए: साधारण सरणी पर विचार करें

$array = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);

यदि आप सरणी कुंजी के आधार पर सरणी फ़िल्टर करना चाहते हैं , तो हमें ARRAY_FILTER_USE_KEY का उपयोग सरणी फ़ंक्शन array_filter के तीसरे पैरामीटर के रूप में करना होगा।

$get_key_res = array_filter($array,"get_key",ARRAY_FILTER_USE_KEY );

यदि आप सरणी कुंजी और सरणी मान के आधार पर सरणी फ़िल्टर करना चाहते हैं , तो हमें ARRAY_FILTER_USE_BOTH को सरणी फ़ंक्शन array_filter के तीसरे पैरामीटर के रूप में उपयोग करने की आवश्यकता है।

$get_both = array_filter($array,"get_both",ARRAY_FILTER_USE_BOTH );

नमूना कॉलबैक कार्य:

 function get_key($key)
 {
    if($key == 'a')
    {
        return true;
    } else {
        return false;
    }
}
function get_both($val,$key)
{
    if($key == 'a' && $val == 1)
    {
        return true;
    }   else {
        return false;
    }
}

इसका उत्पादन होगा

Output of $get_key is :Array ( [a] => 1 ) 
Output of $get_both is :Array ( [a] => 1 ) 

0

इस फ़ंक्शन के साथ आप एक बहुआयामी सरणी फ़िल्टर कर सकते हैं

function filter_array_keys($array,$filter_keys=array()){

    $l=array(&$array);
    $c=1;
    //This first loop will loop until the count var is stable//
    for($r=0;$r<$c;$r++){
        //This loop will loop thru the child element list//
        $keys = array_keys($l[$r]);

        for($z=0;$z<count($l[$r]);$z++){
            $object = &$l[$r][$keys[$z]];

            if(is_array($object)){
                $i=0;
                $keys_on_array=array_keys($object);
                $object=array_filter($object,function($el) use(&$i,$keys_on_array,$filter_keys){
                    $key = $keys_on_array[$i];
                    $i++;

                    if(in_array($key,$filter_keys) || is_int($key))return false;                
                    return true;                        
                });
            }

            if(is_array($l[$r][$keys[$z]])){
                $l[] = &$l[$r][$keys[$z]];
                $c++;
            }//IF           
        }//FOR
    }//FOR  

    return $l[0];

}

0
// Filter out array elements with keys shorter than 4 characters 
// By using Anonymous function with  Closure...     

function comparison($min)
{
   return function($item) use ($min) { 
      return strlen($item) >= $min;   
   }; 
}

$input = array(
  0      => "val 0",
  "one"  => "val one",
  "two"  => "val two",
  "three"=> "val three",
  "four" => "val four",  
  "five" => "val five",    
  "6"    => "val 6"    
);

$output = array_filter(array_keys($input), comparison(4));    

print_r($output);

रन से आउटपुट


0

भोली और बदसूरत (लेकिन लगता है तेज) समाधान?

केवल php 7.3.11 में यह कोशिश की है, लेकिन एक बदसूरत पाश के बारे में एक तिहाई समय में निष्पादित करने के लिए लगता है। कुछ सौ कुंजी के साथ एक सरणी पर समान परिणाम। माइक्रो-अनुकूलन, शायद आरडब्ल्यू में उपयोगी नहीं है, लेकिन यह आश्चर्यजनक और दिलचस्प पाया गया:

$time = microtime(true);
$i = 100000;
while($i) {
    $my_array = ['foo' => 1, 'hello' => 'world'];
    $allowed  = ['foo', 'bar'];
    $filtered = array_filter(
        $my_array,
        function ($key) use ($allowed) {
            return in_array($key, $allowed);
        },
        ARRAY_FILTER_USE_KEY
    );
    $i--;
}
print_r($filtered);
echo microtime(true) - $time . ' on array_filter';

// 0.40600109100342 on array_filter
$time2 = microtime(true);
$i2 = 100000;
while($i2) {
    $my_array2 = ['foo' => 1, 'hello' => 'world'];
    $allowed2  = ['foo', 'bar'];
    $filtered2 = [];
    foreach ($my_array2 as $k => $v) {
        if (in_array($k, $allowed2)) $filtered2[$k] = $v;
    }
    $i2--;
}
print_r($filtered2);
echo microtime(true) - $time2 . ' on ugly loop';
// 0.15677785873413 on ugly loop

-1
$elements_array = ['first', 'second'];

कुछ सरणी तत्वों को हटाने के लिए कार्य करते हैं

function remove($arr, $data) {
    return array_filter($arr, function ($element) use ($data) {
        return $element != $data;
    });
}

कॉल करें और प्रिंट करें

print_r(remove($elements_array, 'second'));

परिणाम Array ( [0] => first )


प्रश्न फ़िल्टरिंग ऐरे कीज़ के बारे में है न कि वैल्यूज़ पर।
२let पर पोलेटेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.