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.
Related
this is the output of my array
[["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"]]
but I would like this to look like
[1,1,1,1,1,1,1]
how would this be achieved in php, it seems everything I do gets put into an object in the array, when I don't want that. I tried using array_values and it succeeded in returning the values only, since I did have keys originally, but this is still not the completely desired outcome
$yourArray = [["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"],["1"]];
use following code in PHP 5.3+
$newArray = array_map(function($v) {
return (int)$v[0];
}, $yourArray);
OR use following code in other PHP version
function covertArray($v) {
return (int)$v[0];
}
$newArray = array_map('covertArray', $yourArray)
You could always do a simple loop...
$newArray = array();
// Assuming $myArray contains your multidimensional array
foreach($myArray as $value)
{
$newArray[] = $value[0];
}
You could beef it up a little and avoid bad indexes by doing:
if( isset($value[0]) ) {
$newArray[] = $value[0];
}
Or just use one of the many array functions to get the value such as array_pop(), array_slice(), end(), etc.
Is there an elegant way of getting values from a massive multi-dimensional array using another array for the keys to lookup?
e.g.
$cats[A][A1][A11][A111] = $val;
$cats[A][A1][A11][A112] = $val;
$cats[A][A1][A12] = $val;
$cats[A][A1][A12][A121] = $val;
$cats[A][A2] = $val;
$cats[A][A2][A21] = $val;
$cats[A][A2][A22] = $val;
$cats[A][A2][A22][A221] = $val;
$cats[A][A2][A22][A222] = $val;
access values from $cats using $keys = Array ('A', 'A2', 'A22', 'A221');
without checking the length of $keys and doing something like...
switch (count($keys)) {
case 1: $val = $cats[$keys[0]]; break;
case 2: $val = $cats[$key[0]][$key[1]]; break;
case 3: $val = $cats[$key[0]][$key[1]][$key[2]]; break;
...
}
many thanks.
Why not use recursion? Something like this:
function get_val($array, $keys) {
if(empty($keys) || !is_array($keys) || !is_array($array)) return $array;
else {
$first_key = array_shift($keys);
return get_val($array[$first_key], $keys);
}
}
I originally had this written in a loop, but changed it to recursive for some reason. It's true, as yeoman said, that a recursive function is more likely than a loop to cause a stack overflow, especially if your array is sufficiently large (PHP does support end recursion), so here's a loop that should accomplish the same purpose:
// given a multidimensional array $array and single-dimensional array of keys $keys
$desired_value = $array;
while(count($keys) > 0) {
$first_key = array_shift($keys);
$desired_value = $desired_value[$first_key];
}
That's fine so far. Otherwise you would need to iterate through array and check deepness. To make it dynamic I am sure you add keys into $keys array when constructing $cats. Using recursion also solution it will take more steps, more memory.
jburbage's suggestion of using recursion is OK in principle, but from what I know, PHP doesn't support end-recursion.
And the question was about a "massive" multidimensional array.
As "massive" suggests great depth in addition to great overall size, it's possible to run into a stack overflow with this solution, as it's usually possible to create data structures on the heap that reach deeper than the stack can cope with via recursion.
The approach is also not desirable from the performance point of view in this case.
Simply refactor jburbage's recursive solution to work in a loop, and you're almost there :-)
Here's jburbage's original suggested code once again:
function get_val($array, $keys) {
if(empty($keys) || !is_array($keys) || !is_array($array)) return $array;
else {
$first_key = array_shift($keys);
return get_val($array[$first_key], $keys);
}
}
How can i create an associative array using the array below, In the fastest and shortest way.
$list = array(array('name', 'aram'), array('family', 'alipoor'));
Something like:
$list = array('name' => 'aram', 'family' => 'alipoor');
The shortest I can think of:
$newlist = array();
foreach ( $list as $keyval ) {
$newlist[ $keyval[0] ] = $keyval[1];
}
$assocArray = array();
foreach($list as $subArray)
{
$assocArray[$subArray[0]] = $subArray[1];
}
Terrible approach, but
$lst = array_combine(array_map('array_shift',$list), array_map('array_pop',$list));
Works only for two-element inner arrays.
Note: three implicit loops in this solution. So better use approach from Rijk van Wel or kevinmajor1 answer
I generally think foreach is pretty well readable and normally pretty fast. If you want it in one line, you can do with foreach as well:
$nl = array(); foreach($list as $k=>$v) $nl[$k]=$v; $list = $nl; unset($nl);
Which is basically demonstrating that there is no value in getting something "single line".
Or if you prefer callbacks for some reason I don't know of:
$list = array_reduce($list, function($v,$w) {return $v+array($w[0]=>$w[1]);}, array());
Which demonstrates that as well. It will hardly be faster than foreach, in any case, the speed differences most certainly do not matter in your case.
Lets say I have an array as follows :
$sampArray = array (1,4,2,1,6,4,9,7,2,9)
I want to remove all the duplicates from this array, so the result should be as follows:
$resultArray = array(1,4,2,6,9,7)
But here is the catch!!! I don't want to use any PHP in built functions like array_unique().
How would you do it ? :)
Here is a simple O(n)-time solution:
$uniqueme = array();
foreach ($array as $key => $value) {
$uniqueme[$value] = $key;
}
$final = array();
foreach ($uniqueme as $key => $value) {
$final[] = $key;
}
You cannot have duplicate keys, and this will retain the order.
A serious (working) answer:
$inputArray = array(1, 4, 2, 1, 6, 4, 9, 7, 2, 9);
$outputArray = array();
foreach($inputArray as $inputArrayItem) {
foreach($outputArray as $outputArrayItem) {
if($inputArrayItem == $outputArrayItem) {
continue 2;
}
}
$outputArray[] = $inputArrayItem;
}
print_r($outputArray);
This depends on the operations you have available.
If all you have to detect duplicates is a function that takes two elements and tells if they are equal (one example will be the == operation in PHP), then you must compare every new element with all the non-duplicates you have found before. The solution will be quadratic, in the worst case (there are no duplicates), you need to do (1/2)(n*(n+1)) comparisons.
If your arrays can have any kind of value, this is more or less the only solution available (see below).
If you have a total order for your values, you can sort the array (n*log(n)) and then eliminate consecutive duplicates (linear). Note that you cannot use the <, >, etc. operators from PHP, they do not introduce a total order. Unfortunately, array_unique does this, and it can fail because of that.
If you have a hash function that you can apply to your values, than you can do it in average linear time with a hash table (which is the data structure behind an array). See
tandu's answer.
Edit2: The versions below use a hashmap to determine if a value already exists. In case this is not possible, here is another variant that safely works with all PHP values and does a strict comparison (Demo):
$array = array (1,4,2,1,6,4,9,7,2,9);
$unique = function($a)
{
$u = array();
foreach($a as $v)
{
foreach($u as $vu)
if ($vu===$v) continue 2
;
$u[] = $v;
}
return $u;
};
var_dump($unique($array)); # array(1,4,2,6,9,7)
Edit: Same version as below, but w/o build in functions, only language constructs (Demo):
$array = array (1,4,2,1,6,4,9,7,2,9);
$unique = array();
foreach($array as $v)
isset($k[$v]) || ($k[$v]=1) && $unique[] = $v;
var_dump($unique); # array(1,4,2,6,9,7)
And in case you don't want to have the temporary arrays spread around, here is a variant with an anonymous function:
$array = array (1,4,2,1,6,4,9,7,2,9);
$unique = function($a) /* similar as above but more expressive ... ... you have been warned: */ {for($v=reset($a);$v&&(isset($k[$v])||($k[$v]=1)&&$u[]=$v);$v=next($a));return$u;};
var_dump($unique($array)); # array(1,4,2,6,9,7)
First was reading that you don't want to use array_unique or similar functions (array_intersect etc.), so this was just a start, maybe it's still of som use:
You can use array_flip PHP Manual in combination with array_keys PHP Manual for your array of integers (Demo):
$array = array (1,4,2,1,6,4,9,7,2,9);
$array = array_keys(array_flip($array));
var_dump($array); # array(1,4,2,6,9,7)
As keys can only exist once in a PHP array and array_flip retains the order, you will get your result. As those are build in functions it's pretty fast and there is not much to iterate over to get the job done.
<?php
$inputArray = array(1, 4, 2, 1, 6, 4, 9, 7, 2, 9);
$outputArray = array();
foreach ($inputArray as $val){
if(!in_array($val,$outputArray)){
$outputArray[] = $val;
}
}
print_r($outputArray);
You could use an intermediate array into which you add each item in turn. prior to adding the item you could check if it already exists by looping through the new array.
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.