PHP - वस्तुओं की एक सरणी से एक संपत्ति निकालना


128

मुझे बिल्लियों की वस्तुओं का एक समूह मिला है:

$cats = Array
    (
        [0] => stdClass Object
            (
                [id] => 15
            ),
        [1] => stdClass Object
            (
                [id] => 18
            ),
        [2] => stdClass Object
            (
                [id] => 23
            )
)

और मैं 1 पंक्ति में बिल्लियों की आईडी की एक सरणी निकालना चाहता हूं (न तो फ़ंक्शन और न ही लूप)।

मैं का उपयोग array_walkकरने के बारे में सोच रहा था, create_functionलेकिन मुझे नहीं पता कि यह कैसे करना है।

कोई उपाय?


मैं एक लूप का उपयोग नहीं करना चाहता क्योंकि मैं परिणाम को 1 पंक्ति में निर्दिष्ट करने में सक्षम होना चाहता हूं: $ बिल्लियों_आईडी = myfunction ($ बिल्लियों); / * को ऐरे (15, 18, 23) * /
अबर्नियर जूल

जवाबों:


150

यदि आपके पास PHP 5.5 या बाद का संस्करण है , तो बिल्ट इन फंक्शन का उपयोग करना सबसे अच्छा तरीका है array_column():

$idCats = array_column($cats, 'id');

लेकिन बेटे को एक सरणी होना चाहिए या एक सरणी में परिवर्तित होना चाहिए


12
यह वास्तव में सबसे अच्छा जवाब है
दिमित्री बुस्लाव

1
सबसे अच्छा समाधान, लेकिन केवल php 5.5 और बाद के
संस्करण के

2
किसी को भी 5.5 के साथ किसी भी अधिक कोडन नहीं किया जाना चाहिए। 3.5 वर्ष पुराना प्रोग्रामिंग भाषा संस्करण ...
तोस्कान

11
यह समाधान सवाल का जवाब नहीं है क्योंकि, array_columnएक साथ काम नहीं करता arrayकी objectसब पर है। चूंकि PHP 7.0.0 संभव है: stackoverflow.com/a/23335938/655224
algorhythm

1
यह तभी काम कर रहा है जब ऑब्जेक्ट प्रॉपर्टी की सार्वजनिक पहुंच है।
करोल गेसनिका

154

चेतावनी create_function() को 7.2.0 के रूप में परिभाषित किया गया है। इस फ़ंक्शन पर भरोसा करना बहुत हतोत्साहित करता है।

आप array_map()फ़ंक्शन का उपयोग कर सकते हैं ।
यह करना चाहिए:

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);

54
यह सही समाधान है और इस तथ्य को जन्म देगा कि प्रत्येक आगामी अनुचर "wtf" d होगा: D
Andreas Klinger

4
केवल एक चीज जो मुझे इस समाधान के बारे में नापसंद है वह है create_function का उपयोग।
इओनु

4
आप एक लैम्ब्डा फ़ंक्शन का उपयोग कर सकते हैं लेकिन बहुत से लोग PHP 5.3
ग्रेग

26
यहाँ हम चलते हैं: $project_names = array_map(function($project) { return $project->name ;}, $projects );हालाँकि, यह इस ब्लॉग पोस्ट में बताया गया है कि यह इस तरह से 2.5 गुना धीमा / मेमोरी इंटेंसिव हो सकता है।
15

7
मुझे पता चला कि हर बार जब create_functionमेमोरी के साथ फंक्शन बनाया जाता है तो वह बड़ा हो जाता है। यदि आप अनंत लूप्स के साथ एक प्रोग्राम लिखते हैं और इसके array_mapसाथ कॉल करते हैं create_functionतो आपको हमेशा कुछ समय में एक Out of memory...त्रुटि मिलेगी । तो प्रयोग create_functionऔर उपयोग न करेंarray_map(function($o) { return $o->id; }, $objects);
algorhythm

87

समाधान आपके द्वारा उपयोग किए जा रहे PHP संस्करण पर निर्भर करता है। कम से कम 2 समाधान हैं:

पहले (नए PHP संस्करण)

जैसा कि @JosepAlsina ने कहा कि सबसे अच्छा और सबसे छोटा समाधान पहले उपयोग करना है array_column:

$catIds = array_column($objects, 'id');

सूचना: सवाल में प्रयुक्त होने arrayवाले एसर को पुनरावृत्त \stdClassकरने के लिए, यह केवल PHP संस्करणों के साथ संभव है >= 7.0। लेकिन जब एक arrayयुक्त arrays का उपयोग कर आप PHP के बाद से ही कर सकते हैं >= 5.5

दूसरा (पुराने PHP संस्करण)

@Greg ने पुराने PHP संस्करणों में कहा है कि यह करना संभव है:

$catIds = array_map(create_function('$o', 'return $o->id;'), $objects);

लेकिन सावधान रहें: नए PHP संस्करणों में , s >= 5.3.0का उपयोग करना बेहतर है Closure, जैसे निम्नलिखित:

$catIds = array_map(function($o) { return $o->id; }, $objects);


अंतर

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

उनकी तुलना करने के लिए मेमोरी आउटपुट के साथ दोनों उदाहरण:

खराब

while (true)
{
    $objects = array_map(create_function('$o', 'return $o->id;'), $objects);

    echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235616
4236600
4237560
4238520
...

अच्छा

while (true)
{
    $objects = array_map(function($o) { return $o->id; }, $objects);

    echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235136
4235168
4235168
4235168
...


इस पर भी यहां चर्चा हो सकती है

स्मृति रिसाव?! क्या 'array_map' के भीतर 'create_function' का उपयोग करते समय कचरा कलेक्टर सही कर रहा है?


हालाँकि, मैं php 7.2 का उपयोग कर रहा हूँ, लेकिन अगर आप नेमस्पेस क्लास ऑब्जेक्ट का उपयोग कर रहे हैं, और रिक्त सरणी लौटाते हैं, तो यह समाधान की तरह नहीं होगा।
मुहम्मद ओमर असलम

क्या आप एक शोषण पोस्ट कर सकते हैं? आपके संदर्भ को बेहतर ढंग से समझने के लिए एक छोटा स्निपेट?
एलगोरटेड ऑक्ट

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

जब मैं objectअपने समाधान में लिखता हूं तो मेरा मतलब ए objectनहीं है Object। निचली श्रेणी objectसरल वस्तु का वर्णन करती है \stdClass। शायद यही समस्या है। क्या आपकी Objectकोई toArrayविधि है? इसे इस्तेमाल करो। एक सरल objectऔर एक arrayलगभग समान है। निम्नलिखित अपरिवर्तनीय मान्य होना चाहिए ((object)(array)$o) === $o:। लागू करने की __getविधि के दौरान आप अपने वर्ग के गुणों को सभी के लिए सुलभ बना सकते हैं। यह अपेक्षित व्यवहार हो सकता है। लेकिन आप अपने array<Object>उदाहरण के साथ array_mapऔर कॉल कर सकते हैं toArray(यदि मौजूद है) और तब IT भी काम करता है
algorhythm

दूसरा स्निपेट जो मैंने प्रदान किया है वह php, net से है और पहली स्निपेट की तरह ही क्लास ऑब्जेक्ट का उपयोग करता है, हो सकता है कि आप सही हों, हो सकता है कि यह कुछ और हो, जिसे मैं अरेंज थैंक्यू में परिवर्तित करके कोशिश करूंगा।
मुहम्मद ओमर असलम

4
function extract_ids($cats){
    $res = array();
    foreach($cats as $k=>$v) {
        $res[]= $v->id;
    }
    return $res
}

और इसे एक पंक्ति में उपयोग करें :

$ids = extract_ids($cats);

1
धन्यवाद साइलेंटगॉस्ट, लेकिन मेरा सवाल केवल 1 कमांड में $ res प्राप्त करने का है, लूप का उपयोग नहीं करना ...
abernier

2
क्या फर्क पड़ता है? यह लगभग सीधा-सीधा है जैसा कि यह हो जाता है। आप शायद कुछ का उपयोग करके अधिक लाइनों का उपयोग करेंगे array_walk
deceze

@ डिसेज़, एक सुरुचिपूर्ण, सरल और ट्रिक समाधान बस बेहतर दिखता है - विशेष रूप से इस ऑपरेशन के रूप में कुछ समझाने के लिए (उदाहरण के लिए यह कस्टम तर्क नहीं है जो बहुत सारे स्थान और टिप्पणियों का गुणन करता है)। मेरे लिए, कि एक बड़ा फर्क पड़ता है।
चार्ली डालसस

3

कोड

<?php

# setup test array.
$cats = array();
$cats[] = (object) array('id' => 15);
$cats[] = (object) array('id' => 18);
$cats[] = (object) array('id' => 23);

function extract_ids($array = array())
{
    $ids = array();
    foreach ($array as $object) {
        $ids[] = $object->id;
    }
    return $ids;
}

$cat_ids = extract_ids($cats);
var_dump($cats);
var_dump($cat_ids);

?>

आउटपुट

# var_dump($cats);
array(3) {
  [0]=>
  object(stdClass)#1 (1) {
    ["id"]=>
    int(15)
  }
  [1]=>
  object(stdClass)#2 (1) {
    ["id"]=>
    int(18)
  }
  [2]=>
  object(stdClass)#3 (1) {
    ["id"]=>
    int(23)
  }
}

# var_dump($cat_ids);
array(3) {
  [0]=>
  int(15)
  [1]=>
  int(18)
  [2]=>
  int(23)
}

मुझे पता है कि यह एक लूप का उपयोग कर रहा है, लेकिन यह इसे करने का सबसे सरल तरीका है! और एक फ़ंक्शन का उपयोग करके यह अभी भी एक ही लाइन पर समाप्त होता है।


मुझे समझ नहीं आता कि लोग इस तरह के सरल समाधानों का विकल्प क्यों नहीं चुनते हैं। यदि आप मुझसे पूछें तो इस तरह से करना तर्कसंगत लगता है।
टॉम डायर

3

आप इसे आसानी से उज़ो माल के साथ कर सकते हैं

$result = array_map(Functions::extract()->id, $arr);

या एरेस के साथ (ouzo उपहारों से)

$result = Arrays::map($arr, Functions::extract()->id);

चेक आउट: http://ouzo.readthedocs.org/en/latest/utils/functions.html#extract

Ouzo के साथ कार्यात्मक प्रोग्रामिंग भी देखें (मैं लिंक पोस्ट नहीं कर सकता)।


3

चेतावनी create_function() को 7.2.0 के रूप में परिभाषित किया गया है। इस फ़ंक्शन पर भरोसा करना बहुत हतोत्साहित करता है।

PHP में निर्मित लूप्स तेज हैं, फिर लूप्स की व्याख्या की जाती है, इसलिए यह वास्तव में इसे वन-लाइनर बनाने के लिए समझ में आता है:

$result = array();
array_walk($cats, create_function('$value, $key, &$result', '$result[] = $value->id;'), $result)


0
    $object = new stdClass();
    $object->id = 1;

    $object2 = new stdClass();
    $object2->id = 2;

    $objects = [
        $object,
        $object2
    ];

    $ids = array_map(function ($object) {
        /** @var YourEntity $object */
        return $object->id;
        // Or even if you have public methods
        // return $object->getId()
    }, $objects);

आउटपुट : [१, २]


0

create_function()समारोह के रूप में हटा दिया गया है php v7.2.0 । आप array_map()दिए गए अनुसार उपयोग कर सकते हैं ,

function getObjectID($obj){
    return $obj->id;
}

$IDs = array_map('getObjectID' , $array_of_object);

वैकल्पिक रूप से, आप array_column()फ़ंक्शन का उपयोग कर सकते हैं जो इनपुट के एकल कॉलम से मान लौटाता है, जिसे कॉलम_की द्वारा पहचाना जाता है। वैकल्पिक रूप से, इनपुट सरणी के index_key कॉलम से मानों को लौटाए गए सरणी में मानों को अनुक्रमित करने के लिए एक index_key प्रदान किया जा सकता है। आप दिए गए array_column का उपयोग कर सकते हैं,

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