Soru Bir dizinin son öğesini silmeden elde etmenin en iyi yolu nedir?


Tamam,

Her şeyi biliyorum array_pop()ama bu son unsuru siler. Bir dizinin son öğesini silmeden elde etmenin en iyi yolu nedir?

EDIT: İşte bir bonus:

$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');

ya da

$array = array('a', 'b', 'c', 'd');
unset($array[2]);
echo $array[sizeof($array) - 1]; // Output: PHP Notice:  Undefined offset:  2 in - on line 4

308
2017-09-10 18:39


Menşei


İster inanın ister inanmayın ve tekrar kullanmayın, bunu yaptığım en hızlı yollardan biridir. $ Val = $ dizi [] = array_pop ($ dizi); echo $ val; - user2782001
Bu soru birçok seçenekle sonuçlandı. Kendimi seçmeme yardımcı olmak için, en dikkate değer / farklı seçeneklerin bazılarını karşılaştırdım ve sonuçları paylaştım ayrı bir cevap olarak. (: @ user2782001 şimdiye kadarki en beğendiğim yorumu önerdi. :) Katkıda bulunan herkese teşekkürler! - Paul van Leeuwen


Cevaplar:


Kısa ve güzel.

Hata mesajını kaldırmak ve tek liner formunu ve verimli performansı korumak için bir çözüm buldum:

$lastEl = array_values(array_slice($array, -1))[0];

- önceki çözüm

$lastEl = array_pop((array_slice($array, -1)));

Not: Ekstra parantezleri önlemek için gereklidir. PHP Strict standards: Only variables should be passed by reference.


130
2018-03-12 12:20



Tam olarak 5 yıl, 6 ay ve 2 gün sonra, daha üstün bir cevap verdiniz! Teşekkür ederim! ve Stack Overflow teşekkür! - Theodore R. Smith
Greet cevap, ama ekstra parantez ekleyerek biraz hackisch hissediyor. Ayrıca phpStorm bunu bir hata olarak işaretleyecektir. Ek parantez eklemek için ekstra bilgi (phpsadness.com/sad/51). Hatanın üstesinden gelmek için bunu '2-liner' yapabilirdiniz: $array = array_slice($array, -1); $lastEl = array_pop($array); Şahsen bu daha iyi olduğunu düşünüyorum (ayrıştırıcı 'hata') - mauricehofman
Tek katmanlı ve ek değişkensiz olarak stil alabilirsiniz: $ lastEl = array_pop ($ lastEl = (array_slice ($ array, -1))); - rolacja
Dereferansı şu şekilde kullanabilirsiniz: array_slice ($ array, -1) [0] - Vikash
Bu cevabın PHP uyarılarından kaçınmak için hala en az iki çeke ihtiyacı vardır. 1. kontrol et array_size() > 1  2. Dizinin aslında bir dizi olup olmadığını kontrol edin. PHP'nin yerleşik olarak @Iznogood tarafından yanıtına hala bağlıyım end() Fonksiyon zaten tüm zor işleri daha verimli bir şekilde yapar. - Ema4rl


Deneyin

$myLastElement = end($yourArray);

Sıfırlamak için (teşekkürler @hopeseekr):

 reset($yourArray);

Bağlamak Manuel

@David Murdoch ekledi: $myLastElement = end(array_values($yourArray));// and now you don't need to call reset(). E_STRICT'de bu uyarıyı üretir

Strict Standards: Only variables should be passed by reference

Teşekkürler o_O Tync ve herkes!


417
2017-09-10 18:40



ucu ($ dizi); ($ Dizi) reset; sorun çözüldü ;-) - Theodore R. Smith
kullanım $myLastElement = end(array_values($yourArray)); ve şimdi aramanıza gerek yok reset(). - David Murdoch
@DavidMurdoch Belki de, RAM ve CPU'yu, dizi değerleri için temp dizisini oluşturarak ... - Theodore R. Smith
Sunucunuz çok fazla RAM harcarsa, basit bir ekstra işlev çağırmak bir fırsat kesicidir, sunucunuzun yapılandırmasını ve kaynaklarını yeniden incelemenizi öneririm. - Chris Baker
Kesin uyarılardan kaçınmak için ek parantez ekleyin: end((array_values($yourArray))) - DanFromGermany


Bu konudaki birçok cevap bize birçok farklı seçenek sunuyor. Onlardan seçim yapabilmek için onların davranışlarını ve performansını anlamalıydım. Bu cevapta, bulgularımı PHP sürümleriyle karşılaştırmalı olarak paylaşacağım. 5.6.29 ve 7.1.0. Test edeceğim seçenekler:

  • seçenek 1.  $x = array_values(array_slice($array, -1))[0];
  • seçenek 2.  $x = array_slice($array, -1)[0];
  • seçenek 3.  $x = array_pop((array_slice($array, -1)));
  • seçenek 4.  $x = array_pop((array_slice($array, -1, 1)));
  • seçenek 5.  $x = end($array); reset($array);
  • seçenek 6.  $x = end((array_values($array)));
  • seçenek 7.  $x = $array[count($array)-1];
  • seçenek 8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]];
  • seçenek 9.  $x = $array[] = array_pop($array);

Test girişleri:

  • boş  = $array = null;
  • boş = $array = [];
  • last_null = $array = ["a","b","c",null];
  • auto_idx = $array = ["a","b","c","d"];
  • Karıştır = $array = []; $array[1] = "a"; $array[2] = "b"; $array[0] = "c";
  • 100 = $array = []; for($i=0;$i<100;$i++) { $array[] = $i; }
  • 100000 = $array = []; for($i=0;$i<100000;$i++) { $array[] = $i; }

Test için kullanacağım 5.6.29 ve 7.1.0 docker konteynerler gibi:

sudo docker run -it --rm php:5.6.29-cli php -r '<<<CODE HERE>>>'

Yukarıda listelenen her kombinasyon <<option code>>s, yukarıda listelenen test <<input code>>s PHP'nin her iki sürümünde çalıştırılacak. Her bir test çalışması için aşağıdaki kod snippet'i kullanılır:

<<input code>>  error_reporting(E_ALL);  <<option code>>  error_reporting(0); $before=microtime(TRUE); for($i=0;$i<100;$i++){echo ".";for($j=0;$j<1;$j++){  <<option code>>  }}; $after=microtime(TRUE); echo "\n"; var_dump($x); echo round(($after-$before)*10);

Her çalışma için bu, test girişinin son alınan son değerini değiştirir ve bir yinelemenin ortalama süresini yazdırır. nanosaniye cinsinden.

Sonuçlar aşağıdaki gibidir:

 /=======================================================================================================================================================================================================================================================================================================\
||                                                                     ||                            T  E  S  T     I  N  P  U  T     -     5  .  6  .  2  9                            ||                             T  E  S  T     I  N  P  U  T     -     7  .  1  .  0                              ||
||                                                                     ||          null |         empty |     last_null |      auto_idx |       shuffle |           100 |        100000 ||          null |         empty |     last_null |      auto_idx |       shuffle |           100 |        100000 ||
||===========================OPTIONS - ERRORS==========================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<|
|| 1.  $x = array_values(array_slice($array, -1))[0];                  ||       W1 + W2 |            N1 |             - |             - |             - |             - |             - ||       W1 + W2 |            N1 |             - |             - |             - |             - |             - ||
|| 2.  $x = array_slice($array, -1)[0];                                ||            W1 |            N1 |             - |             - |             - |             - |             - ||            W1 |            N1 |             - |             - |             - |             - |             - ||
|| 3.  $x = array_pop((array_slice($array, -1)));                      ||       W1 + W3 |             - |             - |             - |             - |             - |             - ||  W1 + N2 + W3 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||
|| 4.  $x = array_pop((array_slice($array, -1, 1)));                   ||       W1 + W3 |             - |             - |             - |             - |             - |             - ||  W1 + N2 + W3 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||
|| 5.  $x = end($array); reset($array);                                ||       W4 + W5 |             - |             - |             - |             - |             - |             - ||       W4 + W5 |             - |             - |             - |             - |             - |             - ||
|| 6.  $x = end((array_values($array)));                               ||       W2 + W4 |             - |             - |             - |             - |             - |             - ||  W2 + N2 + W4 |            N2 |            N2 |            N2 |            N2 |            N2 |            N2 ||
|| 7.  $x = $array[count($array)-1];                                   ||             - |            N3 |             - |             - |             - |             - |             - ||             - |            N3 |             - |             - |             - |             - |             - ||
|| 8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; ||            W5 |       N3 + N4 |             - |             - |             - |             - |             - ||            W5 |       N3 + N4 |             - |             - |             - |             - |             - ||
|| 9.  $x = $array[] = array_pop($array);                              ||            W3 |             - |             - |             - |             - |             - |             - ||            W3 |             - |             - |             - |             - |             - |             - ||
||=======================OPTIONS - VALUE RETRIEVED=====================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<|
|| 1.  $x = array_values(array_slice($array, -1))[0];                  ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 2.  $x = array_slice($array, -1)[0];                                ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 3.  $x = array_pop((array_slice($array, -1)));                      ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 4.  $x = array_pop((array_slice($array, -1, 1)));                   ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 5.  $x = end($array); reset($array);                                ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 6.  $x = end((array_values($array)));                               ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |   bool(false) |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 7.  $x = $array[count($array)-1];                                   ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "b" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "b" |       int(99) |  int(9999999) ||
|| 8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
|| 9.  $x = $array[] = array_pop($array);                              ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||          NULL |          NULL |          NULL | string(1) "d" | string(1) "c" |       int(99) |  int(9999999) ||
||================OPTIONS - NANOSECONDS PER ITERATION==================++===============+===============+===============+===============+===============+===============+===============++===============+===============+===============+===============+===============+===============+===============<|
|| 1.  $x = array_values(array_slice($array, -1))[0];                  ||           681 |           413 |           320 |           321 |           317 |           649 |     1.034.200 ||           642 |           231 |           102 |           110 |           105 |           174 |        86.700 ||
|| 2.  $x = array_slice($array, -1)[0];                                ||           362 |           301 |           206 |           205 |           202 |           530 |     1.006.000 ||           329 |           205 |            63 |            67 |            65 |           134 |        87.000 ||
|| 3.  $x = array_pop((array_slice($array, -1)));                      ||           671 |           183 |           273 |           273 |           269 |           597 |       997.200 ||           807 |           244 |           282 |           305 |           285 |           355 |        87.300 ||
|| 4.  $x = array_pop((array_slice($array, -1, 1)));                   ||           687 |           206 |           303 |           305 |           294 |           625 |     1.003.600 ||           812 |           249 |           284 |           288 |           287 |           359 |        87.200 ||
|| 5.  $x = end($array); reset($array);                                ||           671 |           136 |           137 |           140 |           137 |           137 |           139 ||           632 |            43 |            45 |            46 |            45 |            45 |            45 ||
|| 6.  $x = end((array_values($array)));                               ||           674 |           156 |           278 |           278 |           257 |         2.934 |     8.464.000 ||           835 |           239 |           270 |           274 |           265 |           474 |       815.000 ||
|| 7.  $x = $array[count($array)-1];                                   ||            90 |           257 |           102 |           101 |           101 |           106 |           102 ||            31 |           190 |            32 |            34 |            35 |            32 |            32 ||
|| 8.  $keys = array_keys($array); $x = $array[$keys[count($keys)-1]]; ||           420 |           543 |           365 |           369 |           334 |         3.498 |    12.190.000 ||           358 |           373 |            90 |            97 |            89 |           333 |     1.322.000 ||
|| 9.  $x = $array[] = array_pop($array);                              ||           145 |           150 |           144 |           144 |           143 |           144 |           143 ||            46 |            46 |            46 |            49 |            48 |            46 |            47 ||
 \=======================================================================================================================================================================================================================================================================================================/ 

Yukarıda bahsedilen Warning ve N-otice kodları olarak tercüme:

W1 = Warning: array_slice() expects parameter 1 to be array, null given in Command line code on line 1
W2 = Warning: array_values() expects parameter 1 to be array, null given in Command line code on line 1
W3 = Warning: array_pop() expects parameter 1 to be array, null given in Command line code on line 1
W4 = Warning: end() expects parameter 1 to be array, null given in Command line code on line 1
W5 = Warning: reset() expects parameter 1 to be array, null given in Command line code on line 1
W6 = Warning: array_keys() expects parameter 1 to be array, null given in Command line code on line 1
N1 = Notice: Undefined offset: 0 in Command line code on line 1
N2 = Notice: Only variables should be passed by reference in Command line code on line 1
N3 = Notice: Undefined offset: -1 in Command line code on line 1
N4 = Notice: Undefined index:  in Command line code on line 1

Bu çıktıya dayanarak şu sonuçları çıkardım:

  • Mümkün olduğunda PHP'nin daha yeni bir sürümünü kullan (duh)
  • Büyük diziler için seçenekler aşağıdakilerle sınırlıdır:
    • ya seçenek 5.  $x = end($array); reset($array);
    • veya seçenek 7.  $x = $array[count($array)-1];
    • veya seçenek 9.  $x = $array[] = array_pop($array);
  • Otomatik dizine eklenmemiş diziler için 7 ve 9 numaralı seçenekler bir seçenek değildir

Şahsen ben dizi iç işaretçiler ile kendimi sevmiyorum ve tek bir ifadede bir çözüm tercih. Bu yüzden kendimi kullanacağım kısa hikaye:

  • otomatik dizine diziler için:
    • ya seçenek 7.  $x = $array[count($array)-1];
    • veya seçenek 9.  $x = $array[] = array_pop($array);
  • Otomatik dizine eklenmemiş diziler için: (geçersiz)
    • seçenek 9.  $x = $array[] = array_pop($array);

Biraz bağlı olup olmadığını diziyi yığın veya sıra olarak kullanma 9. seçenekte varyasyonlar yapabilirsiniz.


61
2018-01-22 20:36



Eksik olması için belirli bir seçenek bulursanız, yukarıdaki kod snippet'lerini kopyalayıp daha önce test edilmiş bir seçenekle karşılaştırarak kendiniz test edebilirsiniz. Bu listeye bir seçenek eklemek, karşılaştırılabilir performans sonuçları için tüm kombinasyonları yeniden test ediyor olabilir. Eklenmesi gerektiğini düşündüğünüz belirli bir seçeneğiniz varsa, lütfen bir yorum bırakın, sonra eklemek niyetinde (biraz zaman alabilir). - Paul van Leeuwen
7 numaralı seçeneğim var. Anlaması kolay, basit ve hızlı. - Meam
Bunun için çok teşekkür ederim <3 - shokora
Çok büyük bir cevap, bir yorum olsa da: ilişkisel diziler için seçenek 9 kullanılamaz, çünkü bir önceki anahtar adı yerine otomatik olarak indeksli bir tuşa geri dönüyoruz. - Gras Double
@GrasDouble Teşekkürler, lanet olsun, haklısınız. Bu cevabı yazdıktan sonra PHP'yi fazla kullanmadım: - $. Büyük ilişkisel diziler için yüksek performanslı seçeneklerimiz var mı? - Paul van Leeuwen


Sorun ne array_slice($array, -1)? (Kılavuza bakın: http://us1.php.net/array_slice)

array_slice() bir dizi döndürür. Muhtemelen aradığın şey değil. Öğeyi istiyorsun.


33
2017-11-05 03:40



kullanım array_slice($array, -1)[0] elemanı almak için. - Pang
Cevap bu. "son" Dizinin iç işaretçisini değiştirme? Sorunu sormak ve okumak çok zor! - Gerard ONeill
Bu yaklaşımı seviyorum, ancak Pang'ın işaret ettiği gibi, bu tamamen tam değil. reset(array_slice($array, -1)) başka bir yaklaşımdır (eğer bir hataya sebep olmazsa) array_slice() tek öğeli diziden "küçük" bir şey döndürür - rinogo
Öğeyi doğrudan değiştirebildiğiniz en iyi yaklaşım: array_slice($array, -1)[0] = ""; - HAlex


Referans ile ilgili hatalardan kaçınmanın bir yolu (örn. "End (array_values ​​($ foo))"), call_user_func veya call_user_func_array işlevini kullanmaktır:

// PHP Fatal error: Only variables can be passed by reference
// No output (500 server error)
var_dump(end(array(1, 2, 3)));

// No errors, but modifies the array's internal pointer
// Outputs "int(3)"
var_dump(call_user_func('end', array(1, 2, 3)));

// PHP Strict standards:  Only variables should be passed by reference
// Outputs "int(3)"
var_dump(end(array_values(array(1, 2, 3))));

// No errors, doesn't change the array
// Outputs "int(3)"
var_dump(call_user_func('end', array_values(array(1, 2, 3))));

18
2017-07-12 15:40



Harika bir yaklaşım! ('Bu kabul edilen cevap olmalı') - Typo
Veya sadece ekstra bir parantez ekleyin. Daha kısa ve tatlı: end((array_values($yourArray))) - hasMobi - Android Apps
Ekstra parantez numarası PHP'deki bir hataya dayanır ve bu yaklaşım artık PHP'nin sonraki sürümlerinde (veya en azından PHP 7'de değil) çalışır. - Matt Browne
Ve call_user_func hile PHP 7'de de çalışmıyor. Bence geçici bir değişken yaratıyorsun. - Matt Browne


denenmemiş: Bu işe yaramaz mı?

<?php
$last_element=end(array_values($array));
?>

Array_values ​​tarafından döndürülen dizi geçicidir, işaretçi sıfırlanırsa kimse umurunda değildir.

ve eğer onunla gitmek için anahtara ihtiyacınız varsa, bunu yapacağınızı tahmin ediyorum:

<?php
$last_key=end(array_keys($array));
?>

10
2018-02-08 19:16



OP değilim, ama benim için iyi bir çözüm gibi görünüyor. - liljoshu


Yığınlarla uğraşmak için sık sık buna ihtiyacım var ve her zaman diziyi manipüle etmeden yerel bir işleve sahip olmamasına veya bir şekilde iç işaretçisini kullanmamasına şaşırdım.

Bu yüzden genellikle ilişkisel diziler üzerinde kullanmak için güvenli bir kullanım işlevi taşır.

function array_last($array) {
    if (count($array) < 1)
        return null;

    $keys = array_keys($array);
    return $array[$keys[sizeof($keys) - 1]];
}

8
2017-11-20 22:39





end () bir dizinin son elemanını sağlayacaktır

$array = array('a' => 'a', 'b' => 'b', 'c' => 'c');
echo end($array); //output: c

$array1 = array('a', 'b', 'c', 'd');
echo end($array1); //output: d

6
2018-03-21 11:13



Bu çözüm işe yarar, ancak dizinin iç işaretçisini değiştirir, doğru yol olduğunu düşünmüyorum. - UnixAgain


Dahili işaretçiyi değiştirmeyi umursamıyorsanız (hem dizinlenmiş hem de ilişkilendirici dizileri destekler):

// false if empty array
$last = end($array);

// null if empty array
$last = !empty($array) ? end($array) : null;


İç işaretçiyi değiştirmeyen bir yardımcı işlev istiyorsanız:

function array_last($array) {
    if (empty($array)) {
        return null;
    }
    return end($value);
}

Dizi kopyalandığından, orijinal dizinin iç işaretçisi değiştirilmedi.


Dolayısıyla, aşağıdaki alternatif aslında diziyi kopyalamaması nedeniyle daha hızlıdır, sadece bir dilim yapar:

function array_last($array) {
    if (empty($array)) {
        return null;
    }
    foreach (array_slice($array, -1) as $value) {
        return $value;
    }
}

Bu "foreach / return", ilk (ve burada tek) öğeyi verimli bir şekilde almak için bir ayardır.


Son olarak, en hızlı alternatif ancak sadece dizine diziler için:

$last = !empty($array) ? $array[count($array)-1] : null;

5
2017-07-26 17:38





Bir dizinin son elemanını almak için şunu kullanın:

$lastElement = array_slice($array, -1)[0];

Karşılaştırma

Sırasıyla 100 ve 50.000 element içeren küçük ve büyük dizilerin son elemanını tuttum.

Method: $array[count($array)-1];
Small array (s): 0.000319957733154
Large array (s): 0.000526905059814
Note: Fastest!  count() must access an internal length property.
Note: This method only works if the array is naturally-keyed (0, 1, 2, ...).

Method: array_slice($array, -1)[0];
Small array (s): 0.00145292282104
Large array (s): 0.499367952347

Method: array_pop((array_slice($array, -1, 1)));
Small array (s): 0.00162816047668
Large array (s): 0.513121843338

Method: end($array);
Small array (s): 0.0028350353241
Large array (s): 4.81077480316
Note: Slowest...

PHP Version 5.5.32 kullandım.


5
2018-06-14 05:38



$ array [array_keys ($ array)] [count (array_keys ($ array)) - 1]] 'i nasıl kullanıyoruz? - user2782001
hmm..array_keys oldukça zayıf görünüyor. - user2782001
array_keys kullanarak: küçük dizi için .003 ve büyük için 6.6 var. $ Temp = array_combine kullanarak (array_fill (0, count ($ ar), 0), $ ar); $ temp [count ($ temp) -1]; büyük için 3.1 oldu ve array_values ​​kullanma ($ ar) [sayısı ($ ar) -1] büyük için 3.3 oldu. - user2782001
Büyük dizi (0.0002) öğeyi patlatmak ve tekrar geri koymak için gerçekten daha hızlı ... $ val = $ ar [] = $ dizi_pop ($ ar); - user2782001
@ Westy92 Ünitelerin benchmarkta yanlış görünüyor. Verdiğiniz en küçük sayı 0.00031 ... mikrosaniye yaklaşık 0.3 nanosaniyedir. Bu, testinizin yeni bir bilgisayarınız varsa çalıştırmak için bir saat tıklaması olduğu anlamına gelir. Sanırım ikiniz de demek istediniz milisaniye ya da muhtemelen saniye. - cesoid