Array PHP dihapus dengan nilai (bukan kunci)

886

Saya memiliki array PHP sebagai berikut:

$messages = [312, 401, 1599, 3, ...];

Saya ingin menghapus elemen yang mengandung nilai $del_val(misalnya, $del_val=401), tetapi saya tidak tahu kuncinya. Ini mungkin membantu: setiap nilai hanya dapat berada di sana satu kali .

Saya mencari fungsi paling sederhana untuk melakukan tugas ini.

Adam Strudwick
sumber
1
@Adam Strudwick Tetapi jika Anda memiliki banyak penghapusan pada array ini, apakah akan lebih baik untuk mengulanginya sekali dan membuat kuncinya sama dengan nilai?
dzona
Pertanyaan yang sama: stackoverflow.com/questions/1883421/…
Eric Lavoie
duplikat yang memungkinkan dari PHP Hapus elemen dari array
Alex

Jawaban:

1566

Menggunakan array_search()dan unset, coba yang berikut ini:

if (($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}

array_search()mengembalikan kunci elemen yang ditemukannya, yang dapat digunakan untuk menghapus elemen itu dari array asli menggunakan unset(). Ini akan kembali FALSEpada kegagalan, namun itu dapat mengembalikan nilai false-y pada kesuksesan (kunci Anda mungkin 0misalnya), itulah mengapa !==operator perbandingan ketat digunakan.

The if()pernyataan akan memeriksa apakah array_search()kembali nilai, dan hanya akan melakukan tindakan jika hal itu.

Bojangles
sumber
14
Apakah $ messages = array_diff ($ messages, array ($ del_val)) juga berfungsi? Apakah akan lebih baik dalam kinerja?
Adam Strudwick
9
@ Adam Mengapa tidak mengujinya? Perasaan saya adalah bahwa array_diff()akan lebih lambat karena membandingkan dua array, bukan hanya mencari melalui satu seperti array_search().
Bojangles
22
Meskipun ini valid, Anda harus menghindari pemberian nilai dalam pernyataan seperti itu. Itu hanya akan membuat Anda kesulitan.
adlawson
17
Bagaimana jika $keyitu 0?
evan
16
Jika nilai yang Anda cari memiliki kunci 0atau nilai falsey lainnya, itu tidak akan membatalkan nilai dan kode Anda tidak akan berfungsi. Anda harus menguji $key === false. (edit - Anda mendapatkannya)
evan
674

Nah, menghapus elemen dari array pada dasarnya hanya mengatur perbedaan dengan satu elemen.

array_diff( [312, 401, 15, 401, 3], [401] ) // removing 401 returns [312, 15, 3]

Ini menggeneralisasi dengan baik, Anda dapat menghapus elemen sebanyak yang Anda suka pada saat yang sama, jika Anda mau.

Penafian: Perhatikan bahwa solusi saya menghasilkan salinan array yang baru sambil mempertahankan yang lama berbeda dengan jawaban yang diterima yang bermutasi. Pilih yang Anda butuhkan.

Rok Kralj
sumber
32
ini hanya berfungsi untuk objek yang dapat dikonversi ke string
nischayn22
7
Saya sepertinya mendapatkan 'Parse Error' karena mengatakan [$element], saya menggunakan array($element)sebagai gantinya. Bukan masalah besar, tetapi hanya ingin siapa pun yang memiliki masalah serupa mengetahui bahwa mereka tidak sendirian
Angad
8
Tentu, saya berasumsi PHP 5.4 sekarang mayoritas untuk menjatuhkan notasi lama. Terima kasih atas komentarnya.
Rok Kralj
22
Perlu dicatat bahwa untuk beberapa alasan array_diffdigunakan (string) $elem1 === (string) $elem2sebagai kondisi kesetaraannya, bukan $elem1 === $elem2seperti yang Anda harapkan. Masalah yang ditunjukkan oleh @ nischayn22 adalah konsekuensi dari ini. Jika Anda ingin sesuatu digunakan sebagai fungsi utilitas yang akan berfungsi untuk array elemen arbitrer (yang mungkin objek), jawaban Bojangle mungkin lebih baik karena alasan ini.
Mark Amery
4
Perhatikan juga bahwa metode ini melakukan pengurutan internal untuk setiap argumen array_diff()dan karenanya mendorong runtime hingga O (n lg n) dari O (n).
Ja͢ck
115

Salah satu cara yang menarik adalah dengan menggunakan array_keys():

foreach (array_keys($messages, 401, true) as $key) {
    unset($messages[$key]);
}

The array_keys()Fungsi membutuhkan dua parameter tambahan untuk kembali hanya kunci untuk nilai tertentu dan apakah pemeriksaan yang ketat diperlukan (yaitu menggunakan === untuk perbandingan).

Ini juga dapat menghapus beberapa item array dengan nilai yang sama (misalnya [1, 2, 3, 3, 4]).

Mendongkrak
sumber
3
@ blasteralfredΨ Pencarian linear adalah O (n); Saya tidak yakin mengapa Anda berpikir itu masalah.
Ja͢ck
1
Ya, ini efektif untuk memilih beberapa item / kunci array.
Oki Erie Rinaldi
3
Ini adalah yang terbaik untuk array yang mungkin tidak mengandung semua nilai unik.
Derokorian
Masalahnya adalah ia meninggalkan indeks kunci yang disortir: [0] - a, [2] - b ([1] hilang tetapi array masih melewatinya)
Rodniko
3
@ Radniko dalam hal ini Anda perlu array_values()juga; kunci yang tersisa masih dalam urutan yang sama, jadi secara teknis itu bukan "tidak disortir"
Ja͢ck
55

Jika Anda tahu pasti bahwa array Anda hanya akan berisi satu elemen dengan nilai itu, Anda bisa melakukannya

$key = array_search($del_val, $array);
if (false !== $key) {
    unset($array[$key]);
}

Namun, jika nilai Anda mungkin muncul lebih dari satu kali dalam array Anda, Anda bisa melakukan ini

$array = array_filter($array, function($e) use ($del_val) {
    return ($e !== $del_val);
});

Catatan: Opsi kedua hanya berfungsi untuk PHP5.3 + dengan Penutupan

adlawson
sumber
41
$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);
Rmannn
sumber
11
Ini hanya berfungsi ketika array Anda tidak mengandung nilai duplikat selain yang Anda coba hapus.
jberculo
2
@ jberculo dan kadang-kadang itu persis apa yang Anda butuhkan, dalam beberapa kasus itu menyelamatkan saya melakukan array yang unik di atasnya aswel
DarkMukke
Mungkin, tapi saya akan menggunakan fungsi yang dirancang khusus untuk melakukan itu, alih-alih hanya efek samping beruntung dari fungsi yang pada dasarnya digunakan dan ditujukan untuk sesuatu yang lain. Ini juga akan membuat kode Anda kurang transparan.
jberculo
Pesan tersebut menyatakan "setiap nilai hanya dapat berada di sana satu kali" ini seharusnya berfungsi. Akan lebih baik jika poster itu menggunakan nama variabel smae dan menambahkan sedikit
penjelasan
2
ternyata ini tercepat dibandingkan dengan solusi yang dipilih, saya melakukan benchmark kecil.
AMB
28

Lihatlah kode berikut:

$arr = array('nice_item', 'remove_me', 'another_liked_item', 'remove_me_also');

Anda dapat melakukan:

$arr = array_diff($arr, array('remove_me', 'remove_me_also'));

Dan itu akan memberi Anda array ini:

array('nice_item', 'another_liked_item')
theCodeMachine
sumber
1
Untuk array asosiatif Anda harus menggunakan array_diff_assoc ()
theCodeMachine
5
Bagaimana ini berbeda dari jawaban ini ?
random_user_name
26

Cara terbaik adalah array_splice

array_splice($array, array_search(58, $array ), 1);

Alasan Terbaik ada di sini di http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/

Airy
sumber
4
Ini tidak akan bekerja pada array asosiatif dan array yang memiliki celah pada kunci mereka, misalnya [1, 2, 4 => 3].
Ja͢ck
Maaf ini tidak akan berhasil. Silakan baca artikel yang saya berikan tautan
Airy
4
Tidak akan. Pertimbangkan susunan komentar saya di atas; setelah saya menggunakan kode Anda untuk menghapus nilai 3, array akan menjadi [1, 2, 3]; dengan kata lain, nilainya tidak dihapus. Untuk lebih jelasnya, saya tidak mengatakan itu gagal di semua skenario, hanya yang ini.
Ja͢ck
1
array_splice adalah metode terbaik, tidak disetel tidak akan menyesuaikan indeks array setelah dihapus
Raaghu
21

Atau sederhananya, cara manual:

foreach ($array as $key => $value){
    if ($value == $target_value) {
        unset($array[$key]);
    }
}

Ini adalah yang paling aman dari mereka karena Anda memiliki kontrol penuh pada array Anda

Victor Priceputu
sumber
1
Menggunakan array_splice()bukannya unset()akan menyusun ulang indeks array juga, yang bisa lebih baik dalam hal ini.
Daniele Orlando
20

Dengan kode berikut, nilai berulang akan dihapus dari $ messages.

$messages = array_diff($messages, array(401));

Syed Abidur Rahman
sumber
3
Terpilih. Itu sudah ada di antara jawaban-jawaban lain, tetapi Anda mengatakan yang terbaik dengan menjaganya tetap sederhana, seperti yang Anda miliki. Jawabannya sederhana "array_diff"
ghbarratt
1
Terlihat sederhana tetapi mengubah kompleksitas dari O (n) ke O (n lg n). Jadi, ini sebenarnya lebih rumit;)
Krzysztof Przygoda
20

Jika Anda memiliki PHP 5.3+, ada kode satu baris:

$array = array_filter($array, function ($i) use ($value) { return $i !== $value; }); 
David Lin
sumber
Apakah kamu yakin Penutupan itu tidak memiliki akses ke $value, jadi itu benar-benar harus dimasukkan ke dalam kelas mini sehingga Anda dapat mengakses $valuedalam penutupan ....
random_user_name
@cale_b, saya telah memperbarui contohnya. Juga inilah refnya
David Lin
3
Anda mungkin juga menulis seluruh basis kode pada satu baris jika Anda menyebutnya "satu kode baris"
Milan Simek
16
function array_remove_by_value($array, $value)
{
    return array_values(array_diff($array, array($value)));
}

$array = array(312, 401, 1599, 3);

$newarray = array_remove_by_value($array, 401);

print_r($newarray);

Keluaran

Array ( [0] => 312 [1] => 1599 [2] => 3 )

tttony
sumber
2
Saya tidak yakin apakah ini lebih cepat karena solusi ini melibatkan beberapa panggilan fungsi.
Julian Paolo Dayag
13

Anda dapat melakukan:

unset($messages[array_flip($messages)['401']]);

Penjelasan : Hapus elemen yang memiliki kunci 401setelah membalik array.

Qurashi
sumber
Anda harus sangat berhati-hati jika ingin mempertahankan negara. karena semua kode masa depan harus memiliki nilai, bukan kunci.
saadlulu
1
@saadlulu $ array pesan tidak akan dibalik karena array_flip () tidak mempengaruhi array asli, sehingga array yang dihasilkan setelah menerapkan baris sebelumnya akan sama kecuali bahwa hasil yang tidak diinginkan akan dihapus.
Qurashi
2
tidak yakin apakah ini benar, bagaimana jika ada beberapa elemen dengan nilai 401?
Zippp
Ini masih akan mempertahankan kunci.
Szabolcs Páll
8

Untuk menghapus beberapa nilai, coba yang ini:

while (($key = array_search($del_val, $messages)) !== false) 
{
    unset($messages[$key]);
}
Rajendra Khabiya
sumber
6

Meminjam logika underscore.JS _.reject dan membuat dua fungsi (orang lebih suka fungsi !!)

array_reject_value: Fungsi ini hanya menolak nilai yang ditentukan (juga berfungsi untuk PHP4,5,7)

function array_reject_value(array &$arrayToFilter, $deleteValue) {
    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if ($value !== $deleteValue) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

array_reject: Fungsi ini hanya menolak metode yang dapat dipanggil (berfungsi untuk PHP> = 5.3)

function array_reject(array &$arrayToFilter, callable $rejectCallback) {

    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if (!$rejectCallback($value, $key)) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

Jadi, dalam contoh kita saat ini, kita dapat menggunakan fungsi di atas sebagai berikut:

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject_value($messages, 401);

atau bahkan lebih baik: (karena ini memberi kita sintaks yang lebih baik untuk digunakan seperti array_filter )

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject($messages, function ($value) {
    return $value === 401;
});

Di atas dapat digunakan untuk hal-hal yang lebih rumit seperti katakanlah kami ingin menghapus semua nilai yang lebih besar atau sama dengan 401, kami cukup melakukan ini:

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});
John Skoumbourdis
sumber
1
Bukankah ini filter yang menciptakan kembali? php.net/manual/en/function.array-filter.php
Richard Duerr
Ya memang. Seperti yang sudah saya katakan di posting "atau bahkan lebih baik: (karena ini memberi kita sintaks yang lebih baik untuk digunakan seperti array_filter)". Terkadang Anda benar-benar hanya perlu memiliki fungsi tolak sebagai garis bawah dan itu sebenarnya kebalikan dari filter (dan Anda perlu mendapatkannya dengan kode sesedikit mungkin). Inilah fungsi yang dilakukan. Ini adalah cara sederhana untuk menolak nilai.
John Skoumbourdis
6
$array = array("apple", "banana",'mango');
$array = array_filter($array, function($v) { return $v != "apple"; });

Coba ini, Ini adalah cara terbaik dan tercepat untuk menghapus elemen berdasarkan nilai

Paras Raiyani
sumber
5

@Bangang jawaban membantu saya. Terima kasih.

Dalam kasus saya, array bisa asosiatif atau tidak, jadi saya menambahkan fungsi berikut

function test($value, $tab) {

 if(($key = array_search($value, $tab)) !== false) {
    unset($tab[$key]); return true;

 } else if (array_key_exists($value, $tab)){
        unset($tab[$value]); return true;

 } else {
    return false; // the $value is not in the array $tab
 }

}

Salam

angeltcho
sumber
4

kode single liner (terima kasih kepada array_diff () ), gunakan yang berikut:

$messages = array_diff($messages, array(401));
Bintang
sumber
4

Jawaban yang diterima mengubah array menjadi array asosiatif, jadi, jika Anda ingin menjadikannya sebagai array non-asosiatif dengan jawaban yang diterima, Anda mungkin harus menggunakan array_valuesjuga.

if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
    $arr = array_values($messages);
}

Referensi ada di sini

SaidbakR
sumber
4

Sesuai kebutuhan Anda, " setiap nilai hanya dapat berada di sana untuk sekali " jika Anda hanya tertarik untuk menjaga nilai-nilai unik dalam array Anda, maka array_unique()mungkin apa yang Anda cari.

Memasukkan:

$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);

Hasil:

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}
Mohd Abdul Mujib
sumber
4

Jika nilai yang ingin Anda hapus adalah, atau bisa, berada dalam array. Gunakan fungsi array_diff . Tampaknya bekerja dengan baik untuk hal-hal seperti ini.

array_diff

$arrayWithValuesRemoved = array_diff($arrayOfData, $arrayOfValuesToRemove);
pengguna1518699
sumber
1
Bagaimana ini berbeda dari jawaban ini ?
random_user_name
4

Saya tahu ini tidak efisien sama sekali tetapi sederhana, intuitif dan mudah dibaca.
Jadi jika seseorang mencari solusi yang tidak terlalu mewah yang dapat diperluas untuk bekerja dengan lebih banyak nilai, atau kondisi yang lebih spesifik .. di sini adalah kode sederhana:

$result = array();
$del_value = 401;
//$del_values = array(... all the values you don`t wont);

foreach($arr as $key =>$value){
    if ($value !== $del_value){
        $result[$key] = $value;
    }

    //if(!in_array($value, $del_values)){
    //    $result[$key] = $value;
    //}

    //if($this->validete($value)){
    //      $result[$key] = $value;
    //}
}

return $result
d.raev
sumber
4

Dapatkan kunci array dengan array_search().

evan
sumber
2
Bagaimana cara saya menghapus nilai IF dan hanya jika saya menemukannya dengan array_search?
Adam Strudwick
3
$ k = array_search ($ needle, $ haystack, true); if ($ k! == false) {unset ($ haystack [$ k]); }
evan
3

Jika Anda tidak tahu kuncinya, itu berarti tidak masalah.

Anda bisa menempatkan nilai sebagai kuncinya, itu berarti akan langsung menemukan nilainya. Lebih baik daripada menggunakan pencarian di semua elemen berulang-ulang.

$messages=array();   
$messages[312] = 312;    
$messages[401] = 401;   
$messages[1599] = 1599;   
$messages[3] = 3;    

unset($messages[3]); // no search needed
Ismael
sumber
Hanya berfungsi untuk objek yang dapat dikonversi ke string.
Emile Bergeron
2

Satu liner menggunakan oroperator:

($key = array_search($del_val, $messages)) !== false or unset($messages[$key]);
Eric
sumber
2

Anda dapat merujuk URL ini : untuk fungsi

array-diff-key()

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_key($array1, $array2));
?>

Maka output harus,

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}
manish1706
sumber
1

Gagasan lain untuk menghapus nilai array, gunakan array_diff. Jika saya mau

$my_array = array(1=>"a", "second_value"=>"b", 3=>"c", "d");
$new_array_without_value_c = array_diff($my_array, array("c"));

(Doc: http://php.net/manual/fr/function.array-diff.php )

Dana
sumber
3
Bagaimana ini berbeda dari jawaban ini ?
random_user_name
1

Saya pikir cara paling sederhana adalah dengan menggunakan fungsi dengan foreach loop:

//This functions deletes the elements of an array $original that are equivalent to the value $del_val
//The function works by reference, which means that the actual array used as parameter will be modified.

function delete_value(&$original, $del_val)
{
    //make a copy of the original, to avoid problems of modifying an array that is being currently iterated through
    $copy = $original;
    foreach ($original as $key => $value)
    {
        //for each value evaluate if it is equivalent to the one to be deleted, and if it is capture its key name.
        if($del_val === $value) $del_key[] = $key;
    };
    //If there was a value found, delete all its instances
    if($del_key !== null)
    {
        foreach ($del_key as $dk_i)
        {
            unset($original[$dk_i]);
        };
        //optional reordering of the keys. WARNING: only use it with arrays with numeric indexes!
        /*
        $copy = $original;
        $original = array();
        foreach ($copy as $value) {
            $original[] = $value;
        };
        */
        //the value was found and deleted
        return true;
    };
    //The value was not found, nothing was deleted
    return false;
};

$original = array(0,1,2,3,4,5,6,7,4);
$del_val = 4;
var_dump($original);
delete_value($original, $del_val);
var_dump($original);

Output akan menjadi:

array(9) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
  [8]=>
  int(4)
}
array(7) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
}
algo
sumber
1

Dengan PHP 7.4 menggunakan fungsi panah:

$messages = array_filter($messages, fn ($m) => $m != $del_val);

Untuk membuatnya array non-asosiatif membungkusnya dengan array_values():

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));
Roy
sumber