More efficient way to go through an array in PHP - php

I've created this method to change every value in an array. I'm kinda new to PHP, so I think there should be a more efficient way to do this.
Here's my code:
foreach($my_array as $key => $value)
{
$my_array[$key] = htmlentities($value);
}
Is there a better way to do this?
Thank you in advance.

You'd probably be better off with array_map
$my_array = array_map( 'htmlentities' , $my_array);

You can reference the array and change it
foreach ($array as &$value) {
$value = $value * 2;
}

When you need to apply a function to the value and reassign it to the value, Galen's answer is a good solution. You could also use array_walk(), although it doesn't read as easily as a nice, simple loop.
When you only need to assign, for example, a primitive value to each element in the array, the following will work.
If your keys are numeric, you can use array_fill():
array_fill(0, sizeof($my_array), "test");
If you're using an associative array, you can probably use array_fill_keys(), with something like:
array_fill_keys(array_keys($my_array), "test");

If you mark $value as a reference (&$value) any change you make on $value will effect the corresponding element in $my_array.
foreach($my_array as $key => &$value)
{
$value = "test";
}
e.g.
$my_array = array(1,2,3,4,5,6);
foreach($my_array as &$value)
{
$value *= 5;
}
echo join($my_array, ', ');
prints
5, 10, 15, 20, 25, 30
(And there's also array_map() if you want to keep the original array.)

foreach($my_array as &$value)
{
$value = "test";
}

You could use array_fill, starting at 0 and going to length count($my_array). Not sure if it's better though.
Edit: Rob Hruska's array_fill_keys code is probably better depending on what you define as better (speed, standards, readability etc).
Edit2: Since you've now edited your question, these options are now no longer appropriate as you require the original value to be modified, not changed entirely.

Related

How to combine array values and separate constants without using foreach construction?

I'm trying to find a simpler way to create new arrays from existing arrays and values. There are two routines I'd like to optimize that are similar in construction. The form of the first one is:
$i = 0;
$new_array = array();
foreach ($my_array as $value) {
$new_array[$i][0] = $constant; // defined previously and unchanging
$new_array[$i][1] = $value; // different for each index of $my_array
$i++;
}
The form of the second one has not one but two different values per constant; notice that $value comes before $key in the indexing:
$i = 0;
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$i][0] = $constant; // defined previously and unchanging
$new_array[$i][1] = $value; // different for each index of $my_array
$new_array[$i][2] = $key; // different for each index of $my_array
$i++;
}
Is there a way to optimize these procedures with shorter and more efficient routines using the array operators of PHP? (There are many, of course, and I can't find one that seems to fit the bill.)
I believe a combination of Wouter Thielen's suggestions regarding the other solutions actually holds the best answer for me.
For the first case I provided:
$new_array = array();
// $my_array is numeric, so $key will be index count:
foreach ($my_array as $key => $value) {
$new_array[$key] = array($constant, $value);
};
For the second case I provided:
// $my_array is associative, so $key will initially be a text index (or similar):
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$key] = array($constant, $value, $key);
};
// This converts the indexes to consecutive integers starting with 0:
$new_array = array_values($new_array);
it is shorter, when you use the array-key instead of the $i-counter
$new_array = array();
foreach ($my_array as $key => $value) {
$new_array[$key][0] = $constant; // defined previously and unchanging
$new_array[$key][1] = $value; // different for each index of $my_array
}
Use array_map:
$new_array = array_map(function($v) use ($constant) {
return array($constant, $v);
}, $my_array);
If you want to use the keys too, for your second case:
$new_array = array_map(function($k, $v) use ($constant) {
return array($constant, $v, $k);
}, array_keys($my_array), $my_array);
Assuming the $constant variable is defined in the caller's scope, you'll need to use use ($constant) to pass it into the function's scope.
array_walk is similar, but modifies the array you pass to it, so if you want to update $my_array itself, use array_walk. Your second case then becomes this:
array_walk($my_array, function(&$val, $key) use($constant) {
$val = array($constant, $val, $key);
});
In both examples above for the second case, you'll end up with an associative array (i.e. with the keys still being the keys for the array). If you want to convert this into a numerically indexed array, use array_values:
$numerically_indexed = array_values($associative);
I asked a question similar to this a few days ago, check it out:
PHP - Fastest way to convert a 2d array into a 3d array that is grouped by a specific value
I think that you have an optimal way when it comes to dealing with large amount of data. For smaller amounts there is a better way as was suggested by the benchmarks in my question.
I think too that readability and understanding the code can also be an issue here and I find that things that you can understand are worth more later on than ideas that you do not really grasp as it generally takes a long time to understand them again as it can be quite confusing while debugging issues.
I would suggest, you take a look at the differences between JSON encoded arrays and serialised arrays as there can be major performance differences when working with the two. It seems that as it is now JSON encoded arrays are a more optimised format (faster) for holding and working with data however this will likely change with PHP 7. It would be useful to note that they are also more portable.
Further Reading:
Preferred method to store PHP arrays (json_encode vs serialize)
http://techblog.procurios.nl/k/n618/news/view/34972/14863/cache-a-large-array-json-serialize-or-var_export.html

Unsetting referenced array items

$arr = array('a' => 1, 'b' => 2);
$xxx = &$arr['a'];
unset($xxx);
print_r($arr); // still there :(
so unset only breaks the reference...
Do you know a way to unset the element in the referenced array?
Yes, I know I could just use unset($arr['a']) in the code above, but this is only possible when I know exactly how many items has the array, and unfortunately I don't.
This question is kind of related to this one (this is the reason why that solution doesn't work)
I may be wrong but I think the only way to unset the element in the array would be to look up the index that matches the value referenced by the variable you have, then unsetting that element.
$arr = array('a' => 1, 'b' => 2);
$xxx = &$arr['a'];
$keyToUnset = null;
foreach($arr as $key => $value)
{
if($value === $xxx)
{
$keyToUnset = $key;
break;
}
}
if($keyToUnset !== null)
unset($arr[$keyToUnset]);
$unset($xxx);
Well, anyway, something along those lines. However, keep in mind that this is not super efficient because each time you need to unset an element you have to iterate over the full array looking for it.
Assuming you have control over how $xxx is used, you may want to consider using it to hold the key in the array, instead of a reference to the element at the key. That way you wouldn't need to search the array when you wanted to unset the element. But you would have to replace all sites that use $xxx with an array dereference:
$arr = array('a' => 1, 'b' => 2);
$xxx = 'a';
// instead of $xxx, use:
$arr[$xxx];
// to unset, simply
unset($arr[$xxx]);
When you unset the reference, you just break the binding between variable name and variable content. This does not mean that variable content will be destroyed.
And with respect to the code above - I do not think there is need in separate key
foreach($arr as $key => $value)
{
if($value === $xxx)
{
unset($arr[$key]);
break;
}
}
The simple answer:
$arr = array('a' => 1, 'b' => 2);
$xxx = 'a';
unset($arr[$xxx]);
print_r($arr); // gone :)
i.e.. You probably don't ever really need a reference. Just set $xxx to the appropriate key.

Change variable name in loop

$index = 0;
foreach ($sxml->entry as $entry) {
$array + variable index number here = array('title' => $title);
$index++;
}
I'm trying to change an array name depending on my index count. Is it possible to change variable name (ie. $array1, $array2 $array3 etc.) in the loop?
Edit:
After the loop has finished, I will generate a number number (depending on the count of $index) and then use this array... probably it's a stupid way of accomplishing what Im trying to do, but I don't have a better idea.
You might want to try this instead:
$index = 0;
$arrays = array();
foreach ($sxml->entry as $entry) {
$arrays[$index] = array('title' => $title);
$index++;
}
While it is technically possible to do what you are asking, using an array of arrays will probably work better from you.
This type of indexing is exactly what arrays are designed for, you have a lot of items and want to be able to refer to them by number.
Unless you have a very specific reason to use the name of the variable to represent it's number you will probably have a much simpler time using it's index in the outer array.
Yes you can user an associate array. Generating a string dynamically based on the iteration number and using that as a key in the array.
You can use variable variables. php.net
PHP supports Variable variables:
$num = 1;
$array_name = 'array' . $num;
$$array_name = array(1,2,3);
print_r($array1);
http://php.net/manual/en/language.variables.variable.php

Remove string from PHP array?

Is it possible to remove a string (see example below) from a PHP array without knowing the index?
Example:
array = array("string1", "string2", "string3", "string4", "string5");
I need to remove string3.
$index = array_search('string3',$array);
if($index !== FALSE){
unset($array[$index]);
}
if you think your value will be in there more than once try using array_keys with a search value to get all of the indexes. You'll probably want to make sure
EDIT:
Note, that indexes remain unchanged when using unset. If this is an issue, there is a nice answer here that shows how to do this using array_splice.
This is probably not the fastest method, but it's a short and neat one line of code:
$array = array_diff($array, array("string3"))
or if you're using PHP >5.4.0 or higher:
$array = array_diff($array, ["string3"])
You can do this.
$arr = array("string1", "string2", "string3", "string4", "string5");
$new_arr=array();
foreach($arr as $value)
{
if($value=="string3")
{
continue;
}
else
{
$new_arr[]=$value;
}
}
print_r($new_arr);
Use a combination of array_search and array_splice.
function array_remove(&$array, $item){
$index = array_search($item, $array);
if($index === false)
return false;
array_splice($array, $index, 1);
return true;
}
You can also try like this.
$array = ["string1", "string2", "string3", "string4", "string5"];
$key = array_search('string3',$array);
unset($array[$key]);
It sort of depends how big the array is likely to be, and there's multiple options.
If it's typically quite small, array_diff is likely the fastest consistent solution, as Jorge posted.
Another solution for slightly larger sets:
$data = array_flip($data);
unset($data[$item2remove]);
$data = array_flip($data);
But that's only good if you don't have duplicate items. Depending on your workload it might be advantageous to guarantee uniqueness of items too.

How to get the first item from an associative PHP array?

If I had an array like:
$array['foo'] = 400;
$array['bar'] = 'xyz';
And I wanted to get the first item out of that array without knowing the key for it, how would I do that? Is there a function for this?
reset() gives you the first value of the array if you have an element inside the array:
$value = reset($array);
It also gives you FALSE in case the array is empty.
PHP < 7.3
If you don't know enough about the array (you're not sure whether the first key is foo or bar) then the array might well also be, maybe, empty.
So it would be best to check, especially if there is the chance that the returned value might be the boolean FALSE:
$value = empty($arr) ? $default : reset($arr);
The above code uses reset and so has side effects (it resets the internal pointer of the array), so you might prefer using array_slice to quickly access a copy of the first element of the array:
$value = $default;
foreach(array_slice($arr, 0, 1) as $value);
Assuming you want to get both the key and the value separately, you need to add the fourth parameter to array_slice:
foreach(array_slice($arr, 0, 1, true) as $key => $value);
To get the first item as a pair (key => value):
$item = array_slice($arr, 0, 1, true);
Simple modification to get the last item, key and value separately:
foreach(array_slice($arr, -1, 1, true) as $key => $value);
performance
If the array is not really big, you don't actually need array_slice and can rather get a copy of the whole keys array, then get the first item:
$key = count($arr) ? array_keys($arr)[0] : null;
If you have a very big array, though, the call to array_keys will require significant time and memory more than array_slice (both functions walk the array, but the latter terminates as soon as it has gathered the required number of items - which is one).
A notable exception is when you have the first key which points to a very large and convoluted object. In that case array_slice will duplicate that first large object, while array_keys will only grab the keys.
PHP 7.3+
PHP 7.3 onwards implements array_key_first() as well as array_key_last(). These are explicitly provided to access first and last keys efficiently without resetting the array's internal state as a side effect.
So since PHP 7.3 the first value of $array may be accessed with
$array[array_key_first($array)];
You still had better check that the array is not empty though, or you will get an error:
$firstKey = array_key_first($array);
if (null === $firstKey) {
$value = "Array is empty"; // An error should be handled here
} else {
$value = $array[$firstKey];
}
Fake loop that breaks on the first iteration:
$key = $value = NULL;
foreach ($array as $key => $value) {
break;
}
echo "$key = $value\n";
Or use each() (warning: deprecated as of PHP 7.2.0):
reset($array);
list($key, $value) = each($array);
echo "$key = $value\n";
There's a few options. array_shift() will return the first element, but it will also remove the first element from the array.
$first = array_shift($array);
current() will return the value of the array that its internal memory pointer is pointing to, which is the first element by default.
$first = current($array);
If you want to make sure that it is pointing to the first element, you can always use reset().
reset($array);
$first = current($array);
another easy and simple way to do it use array_values
array_values($array)[0]
Just so that we have some other options: reset($arr); good enough if you're not trying to keep the array pointer in place, and with very large arrays it incurs an minimal amount of overhead. That said, there are some problems with it:
$arr = array(1,2);
current($arr); // 1
next($arr); // 2
current($arr); // 2
reset($arr); // 1
current($arr); // 1 !This was 2 before! We've changed the array's pointer.
The way to do this without changing the pointer:
$arr[reset(array_keys($arr))]; // OR
reset(array_values($arr));
The benefit of $arr[reset(array_keys($arr))]; is that it raises an warning if the array is actually empty.
Test if the a variable is an array before getting the first element. When dynamically creating the array if it is set to null you get an error.
For Example:
if(is_array($array))
{
reset($array);
$first = key($array);
}
We can do
$first = reset($array);
Instead of
reset($array);
$first = current($array);
As reset()
returns the first element of the array after reset;
You can make:
$values = array_values($array);
echo $values[0];
Use reset() function to get the first item out of that array without knowing the key for it like this.
$value = array('foo' => 400, 'bar' => 'xyz');
echo reset($value);
output //
400
Starting with PHP 7.3.0 it's possible to do without resetting the internal pointer. You would use array_key_first. If you're sure that your array has values it in then you can just do:
$first = $array[array_key_first($array)];
More likely, you'll want to handle the case where the array is empty:
$first = (empty($array)) ? $default : $array[array_key_first($array)];
You can try this.
To get first value of the array :-
<?php
$large_array = array('foo' => 'bar', 'hello' => 'world');
var_dump(current($large_array));
?>
To get the first key of the array
<?php
$large_array = array('foo' => 'bar', 'hello' => 'world');
$large_array_keys = array_keys($large_array);
var_dump(array_shift($large_array_keys));
?>
In one line:
$array['foo'] = 400;
$array['bar'] = 'xyz';
echo 'First value= ' . $array[array_keys($array)[0]];
Expanded:
$keys = array_keys($array);
$key = $keys[0];
$value = $array[$key];
echo 'First value = ' . $value;
You could use array_values
$firstValue = array_values($array)[0];
You could use array_shift
I do this to get the first and last value. This works with more values too.
$a = array(
'foo' => 400,
'bar' => 'xyz',
);
$first = current($a); //400
$last = end($a); //xyz

Categories