Unset array element and reseting array values in PHP - php
So I have 2 files. In file 1 I have a table and there I randomly select some fields and store (store in session) them in an array of 2D arrays. When I click on the cell I send this data to my file 2 where I want to check if I clicked on a randomly selected array or not and if I did, I want to remove this 2D array from an main array.
But as soon as I click on one of the selected arrays, the array crashes.
File 1 PHP stuff immportant for this:
session_start();
$_SESSION['arrays'] = $stack ;
File 2 PHP:
session_start();
if (isset($_SESSION['arrays'])) {
$stack = $_SESSION['arrays'];
for ($i = 0; $i< count($stack);$i++){
if($cooridnates == $stack[$i]){
unset($stack[$i]);
array_values($stack);
$i--;
$Result = true;
break;
}
}
$_SESSION['arrays'] = $stack ;
I am suspecting the error might be in 2 things:
count($stack) used, but I don't believe this is the main reason.
The way I store session.
I have tried using manuals from W3Schools and official PHP website and also SOF, but with no use.
But still, I am not sure if the array_values() and unset() is working correctly since the thing chrashes and I can't test it correctly.
I would appreciate any tips.
You need to assign the result of array_values($stack); back to the $stack variable.
$stack = array_values($stack);
There's also no need to use $i-- when you do this, since you're breaking out of the loop after you find a match.
Instead of a loop, you can use array_search():
$pos = array_search($coordinates, $stack);
if ($pos !=== false) {
unset $stack[$pos];
$Result = true;
$stack = array_values($stack);
$_SESSION['arrays'] = $stack;
}
you can do this like that by using foreach loop:
session_start();
if (!empty($_SESSION['arrays'])) {
foreach( $_SESSION['arrays'] as $key => $val){
if($cooridnates == $val){
unset($_SESSION['arrays'][$key]); // if you want this removed value then assign it a variable before unsetting the array
$Result = true;
break;
}
}
}
Related
Looking for an element in an array in PHP
I don't know if I'm managing this array in the best way. The array I have is this: $bass = $_POST['bass']; $selected_scale = $_POST['scale']; $major_scales = array ( array("C","D","E","F","G","A","B","C","D","E","F","G","A","B",), array("C#","D#","E#","F#","G#","A#","B#","C#","D#","E#","F#","G#","A#","B#",), array("Db","Eb","F","Gb","Ab","Bb","C","Db","Eb","F","Gb","Ab","Bb","C",), array("D","E","F#","G","A","B","C#","D","E","F#","G","A","B","C#"), array("D#","E#","F##","G#","A#","B#","C##","D#","E#","F##","G#","A#","B#","C##"), array("Eb","F","G","Ab","Bb","C","D","Eb","F","G","Ab","Bb","C","D"), array("E","F#","G#","A","B","C#","D#","E","F#","G#","A","B","C#","D#"), array("E#","F##","G##","A#","B#","C##","D##","E#","F##","G##","A#","B#","C##","D##"), array("Fb","Gb","Ab","Bbb","Cb","Db","Eb","Fb","Gb","Ab","Bbb","Cb","Db","Eb"), array("F","G","A","Bb","C","D","E","F","G","A","Bb","C","D","E"), array("F#","G#","A#","B","C#","D#","E#","F#","G#","A#","B","C#","D#","E#"), array("Gb","Ab","Bb","Cb","Db","Eb","F","Gb","Ab","Bb","Cb","Db","Eb","F"), array("G","A","B","C","D","E","F#","G","A","B","C","D","E","F#"), array("G#","A#","B#","C#","D#","E#","F##","G#","A#","B#","C#","D#","E#","F##"), array("Ab","Bb","C","Db","Eb","F","G","Ab","Bb","C","Db","Eb","F","G"), array("A","B","C#","D","E","F#","G#","A","B","C#","D","E","F#","G#"), array("A#","B#","C##","D#","E#","F##","G##","A#","B#","C##","D#","E#","F##","G##"), array("Bb","C","D","Eb","F","G","A","Bb","C","D","Eb","F","G","A"), array("B","C#","D#","E","F#","G#","A#","B","C#","D#","E","F#","G#","A#"), array("B#","C##","D##","E#","F##","G##","A##","B#","C##","D##","E#","F##","G##","A##"), array("Cb","Db","Eb","Fb","Gb","Ab","Bb","Cb","Db","Eb","Fb","Gb","Ab","Bb") ); $bass is a string, like the one inside the arrays. The $selected_scale is just a number. What I'm trying to do is to find the $bass in one of those array in the position of $selected_scale. Basically, $bass = $major_scales[$selected_scale]. Therefore I want to create a loop in order to get the elements after that. But I don't know how to manage in this case the situation. I've looked everything in internet and try various solutions without success. I'd like to know how can I do it. Thanks
Try to use next loop: // if value exists in mentioned index if (in_array($bass,$major_scales[$selected_scale])){ // index of that value in that array $tmp_ind = array_search($bass,$major_scales[$selected_scale]); // length of the array $len = count($major_scales[$selected_scale]); // store values after this value $res = []; for ($i=$tmp_ind;$i<$len;$i++){ $res[$i] = $major_scales[$selected_scale][$i]; } } print_r($res); Demo1 If you need to find value by index $selected_scale in one of these arrays and also store values after this position: foreach($major_scales as $ar){ if ($ar[$selected_scale] == $bass){ // length of the array $len = count($ar); // store values after this value $res = []; for ($i=$selected_scale;$i<$len;$i++){ $res[$i] = $ar[$i]; } } } print_r($res); Demo2
Is there a way to generate new array variables in a loop in PHP?
I am looking for a way to create new arrays in a loop. Not the values, but the array variables. So far, it looks like it's impossible or complicated, or maybe I just haven't found the right way to do it. For example, I have a dynamic amount of values I need to append to arrays. Let's say it will be 200 000 values. I cannot assign all of these values to one array, for memory reasons on server, just skip this part. I can assign a maximum amount of 50 000 values per one array. This means, I will need to create 4 arrays to fit all the values in different arrays. But next time, I will not know how many values I need to process. Is there a way to generate a required amount of arrays based on fixed capacity of each array and an amount of values? Or an array must be declared manually and there is no workaround? What I am trying to achieve is this: $required_number_of_arrays = ceil(count($data)/50000); for ($i = 1;$i <= $required_number_of_arrays;$i++) { $new_array$i = array(); foreach ($data as $val) { $new_array$i[] = $val; } } // Created arrays: $new_array1, $new_array2, $new_array3
A possible way to do is to extend ArrayObject. You can build in limitation of how many values may be assigned, this means you need to build a class instead of $new_array$i = array(); However it might be better to look into generators, but Scuzzy beat me to that punchline. The concept of generators is that with each yield, the previous reference is inaccessible unless you loop over it again. It will be in a way, overwritten unlike in arrays, where you can always traverse over previous indexes using $data[4]. This means you need to process the data directly. Storing the yielded data into a new array will negate its effects. Fetching huge amounts of data is no issue with generators but one should know the concept of them before using them.
Based on your comments, it sounds like you don't need separate array variables. You can reuse the same one. When it gets to the max size, do your processing and reinitialize it: $max_array_size = 50000; $n = 1; $new_array = []; foreach ($data as $val) { $new_array[] = $val; if ($max_array_size == $n++) { // process $new_array however you need to, then empty it $new_array = []; $n = 1; } } if ($new_array) { // process the remainder if the last bit is less than max size }
You could create an array and use extract() to get variables from this array: $required_number_of_arrays = ceil($data/50000); $new_arrays = array(); for ($i = 1;$i <= $required_number_of_arrays;$i++) { $new_arrays["new_array$i"] = $data; } extract($new_arrays); print_r($new_array1); print_r($new_array2); //...
I think in your case you have to create an array that holds all your generated arrays insight. so first declare a variable before the loop. $global_array = []; insight the loop you can generate the name and fill that array. $global_array["new_array$i"] = $val; After the loop you can work with that array. But i think in the end that won't fix your memory limit problem. If fill 5 array with 200k entries it should be the same as filling one array of 200k the amount of data is the same. So it's possible that you run in both ways over the memory limit. If you can't define the limit it could be a problem. ini_set('memory_limit', '-1'); So you can only prevent that problem in processing your values directly without saving something in an array. For example if you run a db query and process the values directly and save only the result. You can try something like this: foreach ($data as $key => $val) { $new_array$i[] = $val; unset($data[$key]); } Then your value is stored in a new array and you delete the value of the original data array. After 50k you have to create a new one. Easier way use array_chunk to split your array into parts. https://secure.php.net/manual/en/function.array-chunk.php
There's non need for multiple variables. If you want to process your data in chunks, so that you don't fill up memory, reuse the same variable. The previous contents of the variable will be garbage collected when you reassign it. $chunk_size = 50000; $number_of_chunks = ceil($data_size/$chunk_size); for ($i = 0; $i < $data_size; $i += $chunk_size) { $new_array = array(); foreach ($j = $i * $chunk_size; $j < min($j + chunk_size, $data_size); $j++) { $new_array[] = get_data_item($j); } } $new_array[$i] serves the same purpose as your proposed $new_array$i.
You could do something like this: $required_number_of_arrays = ceil(count($data)/50000); for ($i = 1;$i <= $required_number_of_arrays;$i++) { $array_name = "new_array_$i"; $$array_name = []; foreach ($data as $val) { ${$array_name}[] = $val; } }
Remove first element from simple array in loop
This question has been asked a thousand times, but each question I find talks about associative arrays where one can delete (unset) an item by using they key as an identifier. But how do you do this if you have a simple array, and no key-value pairs? Input code $bananas = array('big_banana', 'small_banana', 'ripe_banana', 'yellow_banana', 'green_banana', 'brown_banana', 'peeled_banana'); foreach ($bananas as $banana) { // do stuff // remove current item } In Perl I would work with for and indices instead, but I am not sure that's the (safest?) way to go - even though from what I hear PHP is less strict in these things. Note that after foreach has run, I expected var_dump($bananas) to return an empty array (or null, but preferably an empty array).
1st method (delete by value comparison): $bananas = array('big_banana', 'small_banana', 'ripe_banana', 'yellow_banana', 'green_banana', 'brown_banana', 'peeled_banana'); foreach ($bananas as $key=>$banana) { if($banana=='big_banana') unset($bananas[$key]); } 2nd method (delete by key): $bananas = array('big_banana', 'small_banana', 'ripe_banana', 'yellow_banana', 'green_banana', 'brown_banana', 'peeled_banana'); unset($bananas[0]); //removes the first value unset($bananas[count($bananas)-1]); //removes the last value //unset($bananas[n-1]); removes the nth value Finally if you want to reset the keys after deletion process: $bananas = array_map('array_values', $bananas); If you want to empty the array completely: unset($bananas); $bananas= array();
it still has the indexes foreach ($bananas as $key => $banana) { // do stuff unset($bananas[$key]); }
for($i=0; $i<count($bananas); $i++) { //doStuff unset($bananas[$i]); } This will delete every element after its use so you will eventually end up with an empty array. If for some reason you need to reindex after deleting you can use array_values
How about a while loop with array_shift? while (($item = array_shift($bananas)) !== null) { // }
Your Note: Note that after foreach has run, I expected var_dump($bananas) to return an empty array (or null, but preferably an empty array). Simply use unset. foreach ($bananas as $banana) { // do stuff // remove current item unset($bananas[$key]); } print_r($bananas); Result Array ( )
This question is old but I will post my idea using array_slice for new visitors. while(!empty($bananas)) { // ... do something with $bananas[0] like echo $bananas[0].'<br>'; $bananas = array_slice($bananas, 1); }
Delete the whole row from an array in php
How do I delete the whole line from an array? When the delete-button is pressed it should delete the whole line. my array looks like that: $liste[0][0] = email-user1 $liste[0][1]= password-user1 $liste[1][0] = email-user2 $liste[1][1]= password-user2 So if I delete the user one, the user2 should just take the place from user1(which should just disappear). if (isset($_GET['delete'])){ $id=key($_GET['delete']); for ($i = 0; $i < count($liste); $i++){ if ("$i"=="$id"){ unset($liste[$id][0]); unset($liste[$id][1]); unset($liste[$id][2]); } else{ } } update I'm using array_splice($liste, $id, 1); now but everytime I try to save it to the file I get an error: implode(): Invalid arguments passed. For saving it to the file, I use the following function: function saveDataToFile($fileName, $liste){ $file=fopen($fileName,"w"); for ($i = 0; $i < count($liste); $i++) { $zArray=$liste[$i]; $zeile=implode("|", $zArray); if(strlen($zeile) > 0){ $zeile=$zeile."\r\n"; fwrite($file, $zeile); } } fclose($datei); }
Try the below code: $liste[0][0] = "email-user1"; $liste[0][1]= "password-user1"; $liste[1][0] = "email-user2"; $liste[1][1]= "password-user2"; $liste[2][0] = "email-user3"; $liste[2][1]= "password-user3"; unset($liste[1]); // say you want to delete this row $new_arr = $liste; unset($liste); $i=0; foreach($new_arr as $value){ $liste[$i] = $value; $i++; }
You can use array_splice() method: array_splice($liste, $id, 1);
$liste[0][0], $liste[0][1] and $liste[0][2] are in real nothing else than a value array(value, value, value) (the inner array) which is assigned to $liste[0] (the outer array) unsetting this (outer) array value $liste[0] is enough: unset($liste[$id]); If you care about the keys of this array (I see you loop from 0..n), you need to reindex your array using: $liste = array_values($liste); This will make your array behaving more like arrays normally do in other programming languages Good practice is to use foreach instead of for. In this case you don't need to reindex: for ($liste as $key=>$value){ if ("$key"=="$id"){ unset($liste[$key]); } But anyway you don't have to loop through an array just for finding a key. It's enough doing this: if (isset($liste[$id])) { /* optional: check if the key exists */ } unset($liste[$id]);
PHP array copy certain keys, built-in functions? Nested loop performance?
I have a PHP array that I'd like to duplicate but only copy elements from the array whose keys appear in another array. Here are my arrays: $data[123] = 'aaa'; $data[423] = 'bbb'; $data[543] = 'ccc'; $data[231] = 'ddd'; $data[642] = 'eee'; $data[643] = 'fff'; $data[712] = 'ggg'; $data[777] = 'hhh'; $keys_to_copy[] = '123'; $keys_to_copy[] = '231'; $keys_to_copy[] = '643'; $keys_to_copy[] = '712'; $keys_to_copy[] = '777'; $copied_data[123] = 'aaa'; $copied_data[231] = 'ddd'; $copied_data[643] = 'fff'; $copied_data[712] = 'ggg'; $copied_data[777] = 'hhh'; I could just loop through the data array like this: foreach ($data as $key => $value) { if ( in_array($key, $keys_to_copy)) { $copied_data[$key] = $value; } } But this will be happening inside a loop which is retrieving data from a MySQL result set. So it would be a loop nested within a MySQL data loop. I normally try and avoid nested loops unless there's no way of using PHP's built-in array functions to get the result I'm looking for. But I'm also weary of having a nested loop within a MySQL data loop, I don't want to keep MySQL hanging around. I'm probably worrying about nested loop performance unnecessarily as I'll never be doing this for more than a couple of hundred rows of data and maybe 10 keys. But I'd like to know if there's a way of doing this with built-in PHP functions. I had a look at array_intesect_key() but that doesn't quite do it, because my $keys_to_copy array has my desired keys as array values rather than keys. Anyone got any ideas? Cheers, B
I worked it out - I almost had it above.I thought I'd post the answer anyway for completeness. Hope this helps someone out! array_intersect_key($data, array_flip($keys_to_copy)) Use array_flip() to switch $keys_to_copy so it can be used within array_intersect_keys() I'll run some tests to compare performance between the manual loop above, to this answer. I would expect the built-in functions to be faster but they might be pretty equal. I know arrays are heavily optimised so I'm sure it will be close. EDIT: I have run some benchmarks using PHP CLI to compare the foreach() code in my question with the code in my answer above. The results are quite astounding. Here's the code I used to benchmark, which I think is valid: <?php ini_set('max_execution_time', 0);//NOT NEEDED FOR CLI // BUILD RANDOM DATA ARRAY $data = array(); while ( count($data) <= 200000) { $data[rand(0, 500000)] = rand(0, 500000); } $keys_to_copy = array_rand($data, 100000); // FOREACH $timer_start = microtime(TRUE); foreach ($data as $key => $value) { if ( in_array($key, $keys_to_copy)) { $copied_data[$key] = $value; } } echo 'foreach: '.(microtime(TRUE) - $timer_start)."s\r\n"; // BUILT-IN ARRAY FUNCTIONS $timer_start = microtime(TRUE); $copied_data = array_intersect_key($data, array_flip($keys_to_copy)); echo 'built-in: '.(microtime(TRUE) - $timer_start)."s\r\n"; ?> And the results... foreach: 662.217s array_intersect_key: 0.099s So it's much faster over loads of array elements to use the PHP array functions rather than foreach. I thought it would be faster but not by that much!
Why not load the entire result set into an array, then begin processing with nested loops? $query_result = mysql_query($my_query) or die(mysql_error()); $query_rows = mysql_num_rows($query_result); for ($i = 0; $i < $query_rows; $i++) { $row = mysql_fetch_assoc($query_result); // 'key' is the name of the column containing the data key (123) // 'value' is the name of the column containing the value (aaa) $data[$row['key']] = $row['value']; } foreach ($data as $key => $value) { if ( in_array($key, $keys_to_copy)) { $copied_data[$key] = $value; } }