यह देखने के लिए कि क्या एक सरणी के तत्व PHP में दूसरे सरणी में हैं


130

PHP में मेरे पास दो सरणियाँ हैं:

लोग:

Array
(
    [0] => 3
    [1] => 20
)

वांटेड अपराधी:

Array
(
    [0] => 2
    [1] => 4
    [2] => 8
    [3] => 11
    [4] => 12
    [5] => 13
    [6] => 14
    [7] => 15
    [8] => 16
    [9] => 17
    [10] => 18
    [11] => 19
    [12] => 20
)

मैं कैसे पता चलेगा अगर किसी भी के लोग तत्वों में हैं वांटेड अपराधियों सरणी?

इस उदाहरण में, इसे वापस चाहिए trueक्योंकि 20में है चाहता था अपराधी

जवाबों:


204

आप उपयोग कर सकते हैं array_intersect()

$result = !empty(array_intersect($people, $criminals));

8
किसी चर के अलावा किसी भी चीज़ के साथ खाली () का उपयोग नहीं कर सकते।
25'09

@grantwparks फिर क्यों इस फ़ंक्शन के बारे में PHP में डॉक्स कहते हैं कि "रिटर्न FALSE है अगर var मौजूद है और एक गैर-रिक्त, गैर-शून्य मान है। अन्यथा TRUE लौटाता है। निम्नलिखित बातों को खाली माना जाता है: सरणी () (एक खाली सरणी। ) "? स्रोत: php.net/manual/en/function.empty.php
Pere

5
आपके द्वारा लिंक किए गए पृष्ठ से: "PHP 5.5 से पहले, खाली () केवल चर का समर्थन करता है; कुछ भी परिणामस्वरूप एक पार्स त्रुटि होगी। दूसरे शब्दों में, निम्नलिखित काम नहीं करेगा: खाली (ट्रिम ($ नाम))। इसके बजाय। ट्रिम ($ नाम) == का उपयोग करें। "
२२

9
जैसा कि मैंने पाया टिप्पणियों में उल्लेख किया गया है कि !empty अपेक्षा के अनुरूप काम नहीं करता है । इसके बजाय, मैंने इस्तेमाल किया count():!count(array_intersect($people, $criminals));
मैटियोसाइड 550

3
इसे 65 मतों के साथ उत्तर के रूप में क्यों चिह्नित किया जाता है जब यह घातक त्रुटि फेंकता है: लेखन संदर्भ में फ़ंक्शन रिटर्न मान का उपयोग नहीं कर सकता है?
डेव हेक

31

Array_intersect () और count () के बजाय (खाली के बजाय) का उपयोग करने में थोड़ा गलत है।

उदाहरण के लिए:

$bFound = (count(array_intersect($criminals, $people))) ? true : false;

2
इसमें कुछ भी गलत नहीं है, लेकिन इसे count()प्रदर्शन करने वाला नहीं माना जाता है (यदि आप सूक्ष्म अनुकूलन की परवाह करते हैं, तो)
जेक ए। स्मिथ

23

अगर 'खाली' सबसे अच्छा विकल्प नहीं है, तो इसके बारे में क्या:

if (array_intersect($people, $criminals)) {...} //when found

या

if (!array_intersect($people, $criminals)) {...} //when not found

22

वह कोड अमान्य है क्योंकि आप केवल भाषा निर्माण में चर पास कर सकते हैं। empty()एक भाषा निर्माण है।

आपको इसे दो लाइनों में करना होगा:

$result = array_intersect($people, $criminals);
$result = !empty($result);

समस्या यह नहीं है कि यह एक भाषा निर्माण है। समस्या यह है कि यह एक संदर्भ और ग्रेग के एक मूल्य से गुजरने की उम्मीद करता है।
आर्टीफैक्टो

1
@Artefacto, php.net से "नोट: क्योंकि यह एक भाषा का निर्माण है और फ़ंक्शन नहीं है, इसे चर कार्यों का उपयोग करके नहीं बुलाया जा सकता है।" यह बिल्कुल वैसा ही है जैसा पॉल ने कहा।
अनुदान

17

In_array बनाम array_intersect के लिए प्रदर्शन परीक्षण:

$a1 = array(2,4,8,11,12,13,14,15,16,17,18,19,20);

$a2 = array(3,20);

$intersect_times = array();
$in_array_times = array();
for($j = 0; $j < 10; $j++)
{
    /***** TEST ONE array_intersect *******/
    $t = microtime(true);
    for($i = 0; $i < 100000; $i++)
    {
        $x = array_intersect($a1,$a2);
        $x = empty($x);
    }
    $intersect_times[] = microtime(true) - $t;


    /***** TEST TWO in_array *******/
    $t2 = microtime(true);
    for($i = 0; $i < 100000; $i++)
    {
        $x = false;
        foreach($a2 as $v){
            if(in_array($v,$a1))
            {
                $x = true;
                break;
            }
        }
    }
    $in_array_times[] = microtime(true) - $t2;
}

echo '<hr><br>'.implode('<br>',$intersect_times).'<br>array_intersect avg: '.(array_sum($intersect_times) / count($intersect_times));
echo '<hr><br>'.implode('<br>',$in_array_times).'<br>in_array avg: '.(array_sum($in_array_times) / count($in_array_times));
exit;

यहाँ परिणाम हैं:

0.26520013809204
0.15600109100342
0.15599989891052
0.15599989891052
0.1560001373291
0.1560001373291
0.15599989891052
0.15599989891052
0.15599989891052
0.1560001373291
array_intersect avg: 0.16692011356354

0.015599966049194
0.031199932098389
0.031200170516968
0.031199932098389
0.031200885772705
0.031199932098389
0.031200170516968
0.031201124191284
0.031199932098389
0.031199932098389
in_array avg: 0.029640197753906

in_array कम से कम 5 गुना तेज है। ध्यान दें कि परिणाम मिलते ही हम "ब्रेक" कर देते हैं।


बेंचमार्क के लिए धन्यवाद। इसलिए यदि आप जानते हैं कि आप छोटे ऐरे संभाल रहे हैं तो बेहतर है कि आप साथ रहें array_intersect()
Tokeeen.com

issetऔर भी तेज है। और आप सक्षम या अक्षम करने के लिए बूल वैल का उपयोग कर सकते हैं। कुंजी के रूप में भी खोज मान सुनिश्चित करें कि कोई डुप्लिकेट नहीं है। 20array_intersect avg: 0.52077736854553; in_array avg: 0.015597295761108; isset का औसत: 0.0077081203460693'
Cottton

1

आप निम्न प्रकार से in_array का उपयोग भी कर सकते हैं:

<?php
$found = null;
$people = array(3,20,2);
$criminals = array( 2, 4, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
foreach($people as $num) {
    if (in_array($num,$criminals)) {
        $found[$num] = true;
    } 
}
var_dump($found);
// array(2) { [20]=> bool(true)   [2]=> bool(true) }

जबकि array_intersect निश्चित रूप से उपयोग करने के लिए अधिक सुविधाजनक है, यह पता चलता है कि प्रदर्शन के मामले में यह वास्तव में बेहतर नहीं है। मैंने यह स्क्रिप्ट भी बनाई है:

<?php
$found = null;
$people = array(3,20,2);
$criminals = array( 2, 4, 8, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
$fastfind = array_intersect($people,$criminals);
var_dump($fastfind);
// array(2) { [1]=> int(20)   [2]=> int(2) }

फिर, मैंने दोनों स्निपेट क्रमशः: http://3v4l.org/WGhO7/perf#tabs और http://3v4l.org/g1Hnu/perf#tabs पर चलाए और प्रत्येक के प्रदर्शन की जाँच की। दिलचस्प बात यह है कि कुल CPU समय, यानी यूजर टाइम + सिस्टम टाइम PHP5.6 के लिए समान है और मेमोरी भी समान है। PHP5.4 के तहत कुल CPU समय array_intersect की तुलना में in_array के लिए कम है, भले ही मामूली रूप से ऐसा हो।


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

1

यहाँ एक तरह से मैं इसे थोड़ी देर के लिए शोध करने के बाद कर रहा हूँ। मैं एक लारवल एपीआई एंडपॉइंट बनाना चाहता था जो यह जांचता है कि क्या कोई फ़ील्ड "उपयोग में है", इसलिए महत्वपूर्ण जानकारी है: 1) डीबी टेबल? 2) क्या DB कॉलम? और 3) क्या उस कॉलम में कोई मान है जो खोज शब्दों से मेल खाता है?

यह जानकर, हम अपने सहयोगी सरणी का निर्माण कर सकते हैं:

$SEARCHABLE_TABLE_COLUMNS = [
    'users' => [ 'email' ],
];

फिर, हम अपने मान सेट कर सकते हैं जिन्हें हम जाँचेंगे:

$table = 'users';
$column = 'email';
$value = 'alice@bob.com';

फिर, हम प्रत्येक array_key_exists()और in_array()एक अभिभावक के साथ एक, दो कदम के कॉम्बो का उपयोग कर सकते हैं और फिर truthyशर्त पर कार्य कर सकते हैं:

// step 1: check if 'users' exists as a key in `$SEARCHABLE_TABLE_COLUMNS`
if (array_key_exists($table, $SEARCHABLE_TABLE_COLUMNS)) {

    // step 2: check if 'email' is in the array: $SEARCHABLE_TABLE_COLUMNS[$table]
    if (in_array($column, $SEARCHABLE_TABLE_COLUMNS[$table])) {

        // if table and column are allowed, return Boolean if value already exists
        // this will either return the first matching record or null
        $exists = DB::table($table)->where($column, '=', $value)->first();

        if ($exists) return response()->json([ 'in_use' => true ], 200);
        return response()->json([ 'in_use' => false ], 200);
    }

    // if $column isn't in $SEARCHABLE_TABLE_COLUMNS[$table],
    // then we need to tell the user we can't proceed with their request
    return response()->json([ 'error' => 'Illegal column name: '.$column ], 400);
}

// if $table isn't a key in $SEARCHABLE_TABLE_COLUMNS,
// then we need to tell the user we can't proceed with their request
return response()->json([ 'error' => 'Illegal table name: '.$table ], 400);

मैं लारवेल-विशिष्ट PHP कोड के लिए माफी माँगता हूँ, लेकिन मैं इसे छोड़ दूँगा क्योंकि मुझे लगता है कि आप इसे छद्म कोड के रूप में पढ़ सकते हैं। महत्वपूर्ण हिस्सा दो ifबयान हैं जिन्हें समान रूप से निष्पादित किया जाता है।

array_key_exists()और in_array()PHP फ़ंक्शन हैं।

स्रोत:

एल्गोरिथ्म कि मैं ऊपर से पता चला है के बारे में अच्छी बात यह है कि आप इस तरह के रूप में एक REST एंडपॉइंट कर सकते हैं GET /in-use/{table}/{column}/{value}(जहां table, columnहै, और valueचर हैं)।

आप ऐसा कर सकते थे:

$SEARCHABLE_TABLE_COLUMNS = [
    'accounts' => [ 'account_name', 'phone', 'business_email' ],
    'users' => [ 'email' ],
];

और फिर आप जैसे अनुरोध प्राप्त कर सकते हैं:

GET /in-use/accounts/account_name/Bob's Drywall (आपको पिछले भाग को एनोड करने की आवश्यकता हो सकती है, लेकिन आमतौर पर नहीं)

GET /in-use/accounts/phone/888-555-1337

GET /in-use/users/email/alice@bob.com

यह भी ध्यान दें कि कोई भी ऐसा नहीं कर सकता है:

GET /in-use/users/password/dogmeat1337क्योंकि passwordआपके लिए स्वीकृत कॉलम की सूची में सूचीबद्ध नहीं है user

आपको यात्रा की शुभकामनाएं।


मुझे पता नहीं है कि इस प्रश्न के साथ क्या करना है, लेकिन मैंने एक नज़र डाला और: मुझे वास्तव में उम्मीद है कि आप कभी भी गतिशील डेटा का उपयोग नहीं करेंगे $SEARCHABLE_TABLE_COLUMNS! यह एक इंजेक्शन के लिए चिल्लाती है - कोई फर्क नहीं पड़ता कि क्या "अल्ट्रा सुरक्षित फ्रेमवर्क क्वेरी बिल्डर" है कि बीच में मुखौटा और फ़िल्टर तालिका और स्तंभ स्ट्रिंग की कोशिश करता है! अंत में टेबल और कॉलम स्ट्रिंग्स को प्लेसहोल्डर (तैयार किए गए स्टेटमेंट) के माध्यम से नहीं जोड़ा जा सकता है और इसे सीधे डाला जाना चाहिए SELECT ... FROM {$table} WHERE {$column} = :placeholder ....। Ofc एडेप्टर (mysql, mongo, ...) पर निर्भर करता है, लेकिन बचाए जाने के लिए कोई तर्क नहीं है! Pls स्थिर या कोई सूची =)
कॉटन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.