I have a PHP array of associative arrays with the following format:
array(1) {
[0]=>
{ ["name"]=> "Steve Jobs"
["email"]=> "steve#gmail.com" }
}
I'm very new to PHP, but what I want to do is search for a specific email, and if found, delete that specific array (name & email pair) from the array (without leaving an empty space in the array where the removed object used to be).
I found this code here that searches for an entry but returns an array. How would I modify this to delete the found array?
function search($array, $key, $value)
{
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && $array[$key] == $value)
$results[] = $array;
foreach ($array as $subarray)
$results = array_merge($results, search($subarray, $key, $value));
}
return $results;
}
Something like this?
function delete_user(&$arr, $name){
for($i = count($arr)-1; $i >= 0; $i--){
if($arr[$i]["name"] == $name){
unset($arr[$i]);
}
}
}
the &$arr tells PHP to pass the array by reference, so it can be modified from the function, otherwise, it'll be pass-by-value.
You have to use unset to remove an element and use in_array or array_search method to search an element from an array.
unset($array[0]);
Sample from PHP manual (array_search)
function array_key_index(&$arr, $key) {
$i = 0;
foreach(array_keys($arr) as $k) {
if($k == $key) return $i;
$i++;
}
}
I believe there's a small problem with raser's answer. I tried to comment on it, but I can't since I don't have 50 reputation.
Let me know if you agree: count($arr) returns the number of elements in the array. He's using a decremental for loop, except the array's index starts at 0 and his loop ends before it reaches 0, so the first element of the array is never searched. I believe the correct code would be something like:
function delete_user(&$arr, $name){
for($i = count($arr) - 1; $i >= 0; $i--){
if($arr[$i]["name"] == $name){
unset($arr[$i]);
}
}
}
Thanks!
just found array index, and
unset(array(key));
this will not showing that array
Related
on http://php.net/manual/en/function.in-array.php - if you scroll down it gives a function to determine if a string is inside of a query in a multidimensional array. "If you found yourself in need of a multidimensional array in_array like function you can use the one below. Works in a fair amount of time"
Here's original code(working):
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return true;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return true;
$bottom++;
}
return false;
}
What I'm trying to do is instead of returning 'true' or 'false' - i'd like to return the ROW #. So my initial thought was to simply replace 'return true' with 'return $bottom; however it isn't returning the record number.
Modified Function (not working);
function in_multiarray($elem, $array)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem)
return $bottom;
else
if(is_array($array[$bottom]))
if(in_multiarray($elem, ($array[$bottom])))
return $bottom;
$bottom++;
}
return false;
}
Does anyone have an idea how to modify this function to return the ROW number that contains the match?
Here's a sample of the array...
$sample = array
array ("oldpage1.php","newpage1.php"),
array ("oldpage2.php","newpage2.php"),
array ("oldpage3.php","newpage3.php"),
array ("oldpage4.php","newpage4.php"),
array ("oldpage5.php","newpage5.php")
etc.
);
$row = in_multiarray($input, $sample);
Therefore if we know the row # we can fetch the new page with a simple
$newpage=$sample[$row][1]
Thanks!
It's worth noting that a function like in_array is intended to tell you whether or not a value exists inside of an array. What you're looking for seems to be a lot closer to something like array_search, which is designed to actually provide you with the key that points to a given value in the array.
However, because you're using a multi-dimensional array what you're actually looking for is the key that points to the array that contains the value. Hence we can divide and conquer this problem with two simple steps.
Map
Filter
The first step is to map a function in_array to every element in the first array (which is just another array). This will tell us which elements of the primary array contain an array that contains the value we're searching for.
$result = array_map(function($arr) use($search) {
return in_array($search, $arr, true);
}, $arr, [$searchValue]);
The second step is to then return the keys to those arrays (i.e. filter the result).
$keys = array_keys(array_filter($result));
Now you have all the keys of any matching items. If you want to apply as just one custom filter that specifies exactly where in the subarray to look, you could also do it like this.
$search = "oldpage2.php";
$sample = [
["oldpage1.php","newpage1.php"],
["oldpage2.php","newpage2.php"],
["oldpage3.php","newpage3.php"],
["oldpage4.php","newpage4.php"],
["oldpage5.php","newpage5.php"],
];
$keys = array_keys(array_filter($sample, function($arr) use($search) {
return $arr[0] === $search;
}));
var_dump($keys);
And you get...
array(1) {
[0]=>
int(1)
}
So now you know that "oldpage2.php" is in row 1 in $sample[1][0] which means you can do this to get the results out of the array.
foreach($keys as $key) {
echo "{$sample[$key][0]} maps to {$sample[$key][1]}\n";
}
Giving you
oldpage2.php maps to newpage2.php
If you want to return only the first result you could do that as well with a function like this using similar approach.
function getFirstMatch($search, Array $arr) {
foreach($arr as $key => $value) {
if ($value[0] === $search) {
return $value[1];
}
}
}
echo getFirstMatch("oldpage4.php", $sample); // newpage4.php
The Better Alternative
Of course, the better approach is to actually use the oldpage names as the actual keys of the array rather than do this expensive search through the array, because array lookup by key in PHP is just an O(1) operation, whereas this needle/haystack approach is O(N).
So we turn your $samples array into something like this and the search no longer requires any functions...
$samples = [
"oldpage1.php" => "newpage1.php",
"oldpage2.php" => "newpage2.php",
"oldpage3.php" => "newpage3.php",
"oldpage4.php" => "newpage4.php",
"oldpage5.php" => "newpage5.php",
];
Now you can just do something like $newpage = $samples[$search] and you get exactly what you're looking for. So echo $samples["oldpage2.php"] gives you "newpage2.php" directly without the intermediary step of searching through each array.
You can use the following code to get the full path to the value:
function in_multiarray($elem, $array, &$result)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom] == $elem) {
array_unshift($result, $bottom);
return true;
}
else {
if(is_array($array[$bottom])) {
if(in_multiarray($elem, $array[$bottom], $result)) {
array_unshift($result, $bottom);
return true;
}
}
}
$bottom++;
}
array_shift($result);
return false;
}
$sample = array(
array ("oldpage1.php","newpage1.php"),
array ("oldpage2.php","newpage2.php"),
array ("oldpage3.php","newpage3.php"),
array ("oldpage4.php","newpage4.php"),
array ("oldpage5.php","newpage5.php")
);
$input = "newpage5.php";
$result = [];
in_multiarray($input, $sample, $result);
print_r($result);
Path is stored in $result;
I've written the below function, it takes in a 2 dimensional array and return the number of times a key occurs, BUT it feels like i may be reinventing the wheel here, is there an easy way?
function countKeys($array, $key)
{
$results = array();
foreach($array as $row)
{
if (array_key_exists($row[$key], $results))
{
$results[$row[$key]] += 1;
}
else
{
$results[$row[$key]] = 1;
}
}
return $results;
}
To count the keys in a two dimensional array with a search I would do this -
function countKeys($array,$search){
$key_count = array(); // new array
foreach($array as $record) {
$keys = array_keys($record);
foreach($keys as $key){
if($key == $search){ // check against the search term
array_push($key_count, $key); // add the key to the new array
}
}
}
return count($key_count); // just count the new array
}
echo countKeys($records, 'last_name');
EXAMPLE
array_keys()
count()
For a 2 dimensional array try:
$result = count(array_column($array, $key));
PHP >= 5.5.0 needed for array_column() or use the PHP Implementation of array_column()
Just use count() function like:
count($array);
see: http://php.net/manual/pt_BR/function.count.php
You can use this function to count arrays variable as well.
Hope it helps you.
I want to try take only filled rows to another array via array_push but i can't take them dynamically because first index is string, how can i do it properly? Thanks.
<?php
while($i < count($val['error']){
if($val['error'][$i] === 0)
{
array_push($newarray, $val[whatwilliputherebecauseofstringindex][$i]);
}
}
?>
Hi here is the pastebin
<?php
// get keys of original array (name, type, etc..)
$keys = array_keys($array);
// for each error value ...
foreach ($array['error'] as $key => $val) {
// if error is not 0..
if($val !== 0)
{
// for each key in the original array..
foreach ($keys as $k) {
// unset the element of the same iteration
unset($array[$k][$key]);
}
}
}
?>
I have written the following function to search an multi-dimensional array by key, but if I call the function with key uri, it appends arrays having key 0 to the found array. What's wrong?
function search_arr($array, $key, &$found) {
foreach ($array as $k => $each) {
if ($k == $key) {
// output of "print $k = $key" is "0 = uri"
$found[] = $each;
}
if (is_array($each)) {
search_arr($each, $key, $found);
}
}
}
Use === to force a value and type match. You get zeros because comparing 0 and "uri" is true - think of them as both evaluating to 0. For complete details of how PHP handles these 'loose' comparisons, see this section of the manual.
I have an array:
$array=array('key1'=>'value1','key2'=>'value2','value3');
and a foreach:
foreach($array as $v){
//do something
}
Is there a way to know in the foreach which element we are parsing?
(without doing something like:)
$count=0;
foreach($array as $v){
$count++;
// do something
}
thanks
EDIT1:
Sorry maybe I was not clear:
I don't want know the key, but I need to know how many elements are left in the foreach. (that's why I did the example with $count)
You could use a class that extends ArrayIterator:
class FooArrayIterator extends ArrayIterator {
private $offset = 0;
public function next() {
$this->offset++;
return parent::next();
}
public function rewind() {
$this->offset = 0;
parent::rewind();
}
public function seek($offset) {
if ($offset >= 0 && $offset < $this->count()) {
$this->offset = $offset;
}
parent::seek($offset);
}
public function offset() {
return $this->offset;
}
}
Example:
$array = array('value1','value2','value3');
$iter = new FooArrayIterator($array);
foreach ($iter as $v) {
echo ($iter->count() - $iter->offset() - 1).' more';
}
You can get the actual index:
foreach ($array as $index => $value) {
}
If you are working with an associative array there is no way to tell the current position of the internal array pointer. There is only an indirect way: you search for the current key in the keys of the array with:
foreach ($array as $index => $value) {
$position = array_search ($index, array_keys ($array));
echo ($position);
}
... but I guess count++ is a much more resource-friendly way.
You can:
$count = count($array);
foreach($array as $key => $value) {
$count--;
//$count elements are left
}
Yes, sort of.
foreach($array as $key=>$value)
// code
}
$key will be the array key, although if you want an actual integer count of iterations, and the keys are not numbered sequentially, or are strings, you will have to use a counter like in your original post.
Edit: to handle the last element without implementing a counter, you can use (if keys are int)
$foo = ($key == count($array)-1) ? "last element" : "any other element";
(janked from the manual comments - http://php.net/manual/en/control-structures.foreach.php)
Edit: if your keys are not integers, you can create a counter like you have in your code above, and substitute $key with your counter variable.
You're being a bit too picky :)
By the way the trick is to transform an associative array to an indexed array:
foreach ( array_values($array) as $key=>$value ){
echo $key; //yes, it will be an INT
echo ( count($array) - $key );
}
Without some pre-processing, such as your count() version, there isn't any way to know where you are in an associative array. At most you can check if you're at the end with end(), but there's no guarantee as to what order foreach() will retrieve the individual elements. Generally it's the same order they got added to the array, but not guarantees.
Another pre-processing option would be
$keys = array_keys($array);
$cnt = count($keys)
for ($i = 0; $i < $cnt; $i++) {
$element = $array[$keys[$i]];
}
and $i would tell you exactly how far through you've gone.