PHP - Nesneler dizisinden bir özelliği çıkarmak


128

Bir dizi kedi nesnem var:

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

ve 1 satırda bir dizi kedinin kimliklerini çıkarmak istiyorum (bir işlev veya döngü değil).

Ben kullanarak düşünüyordum array_walkile create_functionama bunu nasıl bilmiyorum.

Herhangi bir fikir?


Sonucu 1 satıra atayabilmek istediğim için döngü kullanmak istemiyorum: $ cats_id = myfunction ($ cats); / * Array (15, 18, 23)
döndürmelidir

Yanıtlar:


150

PHP 5.5 veya sonraki bir sürüme sahipseniz , en iyi yol yerleşik işlevi kullanmaktır array_column():

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

Ama oğul bir dizi olmalı veya bir diziye dönüştürülmelidir


12
Bu aslında en iyi cevap
Dmitry Buslaev

1
En iyi çözüm, ancak yalnızca php 5.5 ve üzeri için mevcut
Kızma Birader - Kayıt dışı

2
zaten kimse 5.5 ile kodlamamalı. 3.5 yıllık programlama dili sürümü ...
Toskan

11
Bu çözümler soruyu yanıtlamaz çünkü array_columnan arrayof objects ile hiç çalışmaz . PHP 7.0.0 mümkün olduğundan: stackoverflow.com/a/23335938/655224
algorhythm

1
Yalnızca nesne özelliği genel erişime sahip olduğunda çalışır.
Karol Gasienica

154

Uyarı create_function() PHP 7.2.0 itibariyle KULLANIMDAN KALDIRILMIŞTIR. Bu işleve güvenmek kesinlikle önerilmez.

array_map()Fonksiyonu kullanabilirsiniz .
Bunu yapmalı:

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

54
bu doğru çözüm ve gelecek her geliştiricinin "wtf" olacağı gerçeğine yol açacak. d: D
Andreas Klinger

4
Bu çözümde hoşlanmadığım tek şey, create_function kullanımıdır.
Ionuț G. Stan

4
Bir lambda işlevi kullanabilirsiniz, ancak pek çok kişi PHP 5.3 çalıştırmayacaktır
Greg

26
İşte başlıyoruz: $project_names = array_map(function($project) { return $project->name ;}, $projects );Bununla birlikte, bu blog yazısında , bu şekilde 2,5 kat daha yavaş / bellek yoğun olabileceği belirtiliyor .
2013

7
create_functionHafıza ile her işlev oluşturulduğunda büyüdüğünü öğrendim . Sonsuz döngülere sahip bir program yazarsanız ve içindeki array_mapile çağırırsanız, bazen create_functionher zaman bir Out of memory...hata alırsınız . Bu yüzden kullanmayın create_functionve kullanmayınarray_map(function($o) { return $o->id; }, $objects);
algorhythm

87

Çözüm, kullandığınız PHP sürümüne bağlıdır. En azından 2 çözüm var:

İlk (Daha yeni PHP sürümleri)

@JosepAlsina'nın daha önce söylediği gibi, en iyi ve en kısa çözüm array_columnaşağıdaki gibi kullanmaktır :

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

Not: Soru içinde kullanıldığı gibi arrayiçeren bir es'i yinelemek için \stdClassbu sadece PHP sürümleri ile mümkündür >= 7.0. Ancak, arrayiçeren bir URL kullanırken arrayaynı şeyi PHP'den beri yapabilirsiniz >= 5.5.

İkinci (Eski PHP sürümleri)

@Greg, eski PHP sürümlerinde aşağıdakileri yapmanın mümkün olduğunu söyledi:

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

Ancak dikkatli olun: Daha yeni PHP sürümlerinde >= 5.3.0aşağıdaki Closuregibi s kullanmak daha iyidir :

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


Fark

İlk çözüm yeni bir işlev oluşturur ve bunu RAM'inize yerleştirir. Çöp toplayıcı, önceden oluşturulmuş ve önceden çağrılmış işlev örneğini herhangi bir nedenle bellekten silmez. Ve yaratılan işlev örneğinin bir daha asla çağrılamayacağı gerçeğine bakılmaksızın, çünkü onun için göstericimiz yok. Ve bir dahaki sefere bu kod çağrıldığında, aynı işlev yeniden yaratılacaktır. Bu davranış yavaş yavaş hafızanızı doldurur ...

Karşılaştırmak için bellek çıkışlı her iki örnek:

KÖTÜ

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
...

İYİ

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

    echo memory_get_usage() . "\n";

    sleep(1);
}

// the output
4235136
4235168
4235168
4235168
...


Bu ayrıca burada tartışılabilir

Bellek sızıntısı?! Garbage Collector, 'array_map' içinde 'create_function' kullanılırken doğru yapıyor mu?


php 7.2 kullanmama rağmen, ad alanı sınıf nesneleri kullanıyorsanız ve boş dizi döndürürseniz çözüm işe yaramayacak gibi görünüyor.
Muhammad Omer Aslam

Bir istismar yayınlayabilir misin? Bağlamınızı daha iyi anlamak için kısa bir pasaj?
algorhythm

örneğin, dropbox API SDK tarafından döndürülen model nesnelerinin bir listesine sahip olduğum bu parçacığa bakın ve array_columnbu diziyi kullanmaya çalıştığımızda her zaman boş dönüyor, oysa BU ön bilgi doğru çalışıyor, her ikisi de ikinci parçacığından erişilebilen korumalı özelliğe sahip sadece. Ad alanından başka bir neden bulamadım.
Muhammad Omer Aslam

Çözümümde yazdığımda object, objectbir Object. Alt harfli objectbasit nesneyi tanımlar \stdClass. Belki sorun budur. Senin mu Objectbir var toArrayyöntemini? Bunu kullan. Basit objectve bir arrayneredeyse aynı. Aşağıdaki değişmez geçerli olmalıdır: ((object)(array)$o) === $o. __getYöntemi uygularken , sınıf özelliklerinizi herkes için erişilebilir hale getireceksiniz. Bu beklenen davranış olabilir. Ancak, array<Object>örneğin ile yineleyebilir array_mapve çağırabilirsiniz toArray(varsa) ve ardından BT de çalışır
algorhythm

Sağladığım ikinci kod parçası php, net'ten geliyor ve ilk kod parçacığındaki ile aynı Class nesnesini kullanıyor, belki de haklısınız, belki de onu bir diziye dönüştürerek deneyeceğim başka bir şey teşekkür ederim.
Muhammad Omer Aslam

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

ve tek satırda kullanın :

$ids = extract_ids($cats);

1
Teşekkürler SilentGhost, ama sorum sadece 1 komutta $ res almak üzere, döngü kullanmadan ...
abernier

2
Ne fark eder ki? Bu, olabildiğince basittir. Gibi bir şey kullanarak muhtemelen daha fazla satır kullanacaksınız array_walk.
deceze

@deceze, zarif, basit ve kısa bir çözüm - özellikle bu işlem kadar açıklanabilir bir şey için daha iyi görünüyor (örneğin, bu çok fazla alan ve yorum gerektiren özel bir mantık değildir). Bana göre bu büyük bir fark yaratıyor.
Charlie Dalsass

3

KOD

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

?>

ÇIKTI

# 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)
}

Bir döngü kullandığını biliyorum ama bunu yapmanın en basit yolu bu! Ve bir işlevi kullanarak, yine de tek bir satırda bitiyor.


İnsanların neden böyle basit çözümleri tercih etmediklerini anlamıyorum. Bana sorarsan, bu şekilde yapmak mantıklı görünüyor.
Tom Dyer


3

Uyarı create_function() PHP 7.2.0 itibariyle KULLANIMDAN KALDIRILMIŞTIR. Bu işleve güvenmek kesinlikle önerilmez.

PHP'deki yerleşik döngüler, yorumlanan döngülerden daha hızlıdır, bu nedenle bunu tek satırlık bir döngü yapmak mantıklıdır:

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

1
// $array that contain records and id is what we want to fetch a
$ids = array_column($array, 'id');

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

Çıktı : [1, 2]


0

create_function()İşlev itibariyle önerilmemektedir php v7.2.0 . Verildiği gibi kullanabilirsiniz array_map(),

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

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

Alternatif olarak, array_column()column_key ile tanımlanan girdinin tek bir sütunundan değerleri döndüren işlevi kullanabilirsiniz . İsteğe bağlı olarak, döndürülen dizideki değerleri, girdi dizisinin dizin_anahtar sütunundaki değerlerle dizinlemek için bir dizin_anahtar sağlanabilir. Dizi_sütunu belirtildiği gibi kullanabilirsiniz,

$IDs = array_column($array_of_object , 'id');
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.