Rebase array keys after unsetting elements [duplicate] - php

This question already has answers here:
How to re-index the values of an array in PHP? [duplicate]
(3 answers)
Closed 2 years ago.
I have an array:
$array = array(1,2,3,4,5);
If I were to dump the contents of the array they would look like this:
array(5) {
[0] => int(1)
[1] => int(2)
[2] => int(3)
[3] => int(4)
[4] => int(5)
}
When I loop through and unset certain keys, the index gets all jacked up.
foreach($array as $i => $info)
{
if($info == 1 || $info == 2)
{
unset($array[$i]);
}
}
Subsequently, if I did another dump now it would look like:
array(3) {
[2] => int(3)
[3] => int(4)
[4] => int(5)
}
Is there a proper way to reset the array so it's elements are Zero based again ??
array(3) {
[0] => int(3)
[1] => int(4)
[2] => int(5)
}

Try this:
$array = array_values($array);
Using array_values()

Got another interesting method:
$array = array('a', 'b', 'c', 'd');
unset($array[2]);
$array = array_merge($array);
Now the $array keys are reset.

Use array_splice rather than unset:
$array = array(1,2,3,4,5);
foreach($array as $i => $info)
{
if($info == 1 || $info == 2)
{
array_splice($array, $i, 1);
}
}
print_r($array);
Working sample here.

Just an additive.
I know this is old, but I wanted to add a solution I don't see that I came up with myself. Found this question while on hunt of a different solution and just figured, "Well, while I'm here."
First of all, Neal's answer is good and great to use after you run your loop, however, I'd prefer do all work at once. Of course, in my specific case I had to do more work than this simple example here, but the method still applies. I saw where a couple others suggested foreach loops, however, this still leaves you with after work due to the nature of the beast. Normally I suggest simpler things like foreach, however, in this case, it's best to remember good old fashioned for loop logic. Simply use i! To maintain appropriate index, just subtract from i after each removal of an Array item.
Here's my simple, working example:
$array = array(1,2,3,4,5);
for ($i = 0; $i < count($array); $i++) {
if($array[$i] == 1 || $array[$i] == 2) {
array_splice($array, $i, 1);
$i--;
}
}
Will output:
array(3) {
[0]=> int(3)
[1]=> int(4)
[2]=> int(5)
}
This can have many simple implementations. For example, my exact case required holding of latest item in array based on multidimensional values. I'll show you what I mean:
$files = array(
array(
'name' => 'example.zip',
'size' => '100000000',
'type' => 'application/x-zip-compressed',
'url' => '28188b90db990f5c5f75eb960a643b96/example.zip',
'deleteUrl' => 'server/php/?file=example.zip',
'deleteType' => 'DELETE'
),
array(
'name' => 'example.zip',
'size' => '10726556',
'type' => 'application/x-zip-compressed',
'url' => '28188b90db990f5c5f75eb960a643b96/example.zip',
'deleteUrl' => 'server/php/?file=example.zip',
'deleteType' => 'DELETE'
),
array(
'name' => 'example.zip',
'size' => '110726556',
'type' => 'application/x-zip-compressed',
'deleteUrl' => 'server/php/?file=example.zip',
'deleteType' => 'DELETE'
),
array(
'name' => 'example2.zip',
'size' => '12356556',
'type' => 'application/x-zip-compressed',
'url' => '28188b90db990f5c5f75eb960a643b96/example2.zip',
'deleteUrl' => 'server/php/?file=example2.zip',
'deleteType' => 'DELETE'
)
);
for ($i = 0; $i < count($files); $i++) {
if ($i > 0) {
if (is_array($files[$i-1])) {
if (!key_exists('name', array_diff($files[$i], $files[$i-1]))) {
if (!key_exists('url', $files[$i]) && key_exists('url', $files[$i-1])) $files[$i]['url'] = $files[$i-1]['url'];
$i--;
array_splice($files, $i, 1);
}
}
}
}
Will output:
array(1) {
[0]=> array(6) {
["name"]=> string(11) "example.zip"
["size"]=> string(9) "110726556"
["type"]=> string(28) "application/x-zip-compressed"
["deleteUrl"]=> string(28) "server/php/?file=example.zip"
["deleteType"]=> string(6) "DELETE"
["url"]=> string(44) "28188b90db990f5c5f75eb960a643b96/example.zip"
}
[1]=> array(6) {
["name"]=> string(11) "example2.zip"
["size"]=> string(9) "12356556"
["type"]=> string(28) "application/x-zip-compressed"
["deleteUrl"]=> string(28) "server/php/?file=example2.zip"
["deleteType"]=> string(6) "DELETE"
["url"]=> string(45) "28188b90db990f5c5f75eb960a643b96/example2.zip"
}
}
As you see, I manipulate $i before the splice as I'm seeking to remove the previous, rather than the present item.

I use $arr = array_merge($arr); to rebase an array. Simple and straightforward.

100% working for me ! After unset elements in array you can use this for re-indexing the array
$result=array_combine(range(1, count($your_array)), array_values($your_array));

Late answer but, after PHP 5.3 could be so;
$array = array(1, 2, 3, 4, 5);
$array = array_values(array_filter($array, function($v) {
return !($v == 1 || $v == 2);
}));
print_r($array);

Or you can make your own function that passes the array by reference.
function array_unset($unsets, &$array) {
foreach ($array as $key => $value) {
foreach ($unsets as $unset) {
if ($value == $unset) {
unset($array[$key]);
break;
}
}
}
$array = array_values($array);
}
So then all you have to do is...
$unsets = array(1,2);
array_unset($unsets, $array);
... and now your $array is without the values you placed in $unsets and the keys are reset

In my situation, I needed to retain unique keys with the array values, so I just used a second array:
$arr1 = array("alpha"=>"bravo","charlie"=>"delta","echo"=>"foxtrot");
unset($arr1);
$arr2 = array();
foreach($arr1 as $key=>$value) $arr2[$key] = $value;
$arr1 = $arr2
unset($arr2);

Related

How to merge subarrays using keys and sum the values?

I'm fairly new to PHP and I'm having some trouble with arrays and combining data. I have the following array which has been created from a foreach loop:
array(1) {
[36868]=> int(3)
}
array(1) {
[2112]=> int(3)
}
array(1) {
[35901]=> int(3)
}
array(1) {
[6496]=> int(3)
}
array(1) {
[87]=> int(3)
}
array(1) {
[36868]=> int(3)
}
array(1) {
[68]=> int(3)
}
array(1) {
[9068]=> int(3)
}
array(1) {
[47]=> int(3)
}
The key in each array is a user ID, so I need to preserve this, but I only want one instance of each key and where there are duplicate keys, sum the values. Like so:
array(1) {
[36868]=> int(6)
}
array(1) {
[2112]=> int(3)
}
array(1) {
[35901]=> int(3)
}
array(1) {
[6496]=> int(3)
}
array(1) {
[87]=> int(3)
}
array(1) {
[68]=> int(3)
}
array(1) {
[9068]=> int(3)
}
array(1) {
[47]=> int(3)
}
The I've tried looping through the array:
foreach ($array as $key => &$value) {
if ($value[0] == $value[1]) {
$value[1] += $value[1];
}
}
But with no luck. I've also tried rendering the arrays differently i.e. [userid]=>1,[score]=>3 and I feel like I'm going round in circles a bit, so any help would be hugely appreciated.
$data <-- this is your original array
$result = array_reduce(
$data,
function($carry, $item) {
foreach ($item as $id => $score) {
if (array_key_exists($id, $carry)) {
$carry[$id] += $score;
} else {
$carry[$id] = $score;
}
}
return $carry;
},
[]
);
If you are sure that each item only contains 1 entry you could also simplify the callback to not use foreach:
$result = array_reduce(
$data,
function ($carry, $item) {
$score = reset($item);
$id = key($item);
if (array_key_exists($id, $carry)) {
$carry[$id] += $score;
} else {
$carry[$id] = $score;
}
return $carry;
},
[]
);
You could also keep using foreach instead:
/** foreach to create a $data array like described below and afterwards do this: **/
$result = [];
foreach($data as $row) {
$score = reset($row);
$id = key($row);
if (array_key_exists($id, $result)) {
$result[$id] += $score;
} else {
$result[$id] = $score;
}
}
This will take an array $data like this:
array(
array('1' => 3),
array('1' => 3),
array('2' => 3),
);
and creates the variable $result like this:
array(
'1' => 6,
'2' => 3,
);
Here is a clean method that will not produce Notices. When merge-summing array data the efficient method is to generate temporary keys and use the very fast isset() function. I could have used current() and key() to access the lone subarray element, but the second foreach control structure is actually faster and more compact. (Ref:
https://stackoverflow.com/a/21219594/2943403 )
Code: (Demo)
$array = [
[36868 => 3],
[2112 => 3],
[35901 => 3],
[6496 => 3],
[87 => 3],
[36868 => 3],
[68 => 3],
[9068 => 3],
[47 => 3]
];
$result = [];
foreach ($array as $subarray) {
foreach ($subarray as $k => $v) {
if (!isset($result[$k])) {
$result[$k] = $subarray;
} else {
$result[$k][$k] += $v;
}
}
}
var_export(array_values($result));
Output:
array (
0 =>
array (
36868 => 6,
),
1 =>
array (
2112 => 3,
),
2 =>
array (
35901 => 3,
),
3 =>
array (
6496 => 3,
),
4 =>
array (
87 => 3,
),
5 =>
array (
68 => 3,
),
6 =>
array (
9068 => 3,
),
7 =>
array (
47 => 3,
),
)

Search values in php array

I have an array like this:
array(5) {
[0]=> array(1) { ["go-out"]=> string(7) "#0d4b77" }
[1]=> array(1) { ["cycling"]=> string(7) "#1472b7" }
[2]=> array(1) { ["diving"]=> string(7) "#1e73be" }
[3]=> array(1) { ["exploring"]=> string(7) "#062338" }
[4]=> array(1) { ["eating"]=> string(7) "#f79e1b" }
}
Let's say I have the first value like 'cycling', so how can I find the '#147217' value?
I have been trying a lot of combinations of
foreach ( $array as $key => list($key1 ,$val)) {
if ($key1 === $id) {
return $val;
}
}
But no luck.
Ideas?
You can use array_column -
array_column($your_array, 'cycling');
DEMO
You should also add the checks for key's existence.
you may still make one loop
$id = "cycling";
foreach($array as $val)
if(isset($val[$id])) echo $val[$id];
Demo on Evail.in
I have reformated tour code, try this, that works:
$array = array(
0 => array("go-out" => "#0d4b77"),
1 => array("cycling" => "#1472b7"),
2 => array("diving" => "#1e73be"),
3 => array("exploring" => "#062338"),
4 => array("eating" => "#f79e1b")
);
$id = "cycling";
foreach ($array as $key => $entry) {
if ($entry[$id]) {
echo $entry[$id];
}
}
$array = array(
0 => array("go-out" => "#0d4b77"),
1 => array("cycling" => "#1472b7"),
2 => array("diving" => "#1e73be"),
3 => array("exploring" => "#062338"),
4 => array("eating" => "#f79e1b")
);
$search = "cycling";
foreach ($array as $key => $entry)
if (isset($entry[$search]))
echo $entry[$search];
That works.
Nice day.

Sort then split a PHP array?

Here is a var_dump of my array:
array(6) {
[0]=> string(4) "quack"
["DOG"]=> string(4) "quack"
[1]=> string(4) "quack"
["CAT"]=> string(4) "quack"
[2]=> string(4) "Aaaaarrrrrggggghhhhh"
["CAERBANNOG"]=> string(4) "Aaaaarrrrrggggghhhhh"
}
(just for fun I've included two puns in this code, try and find them!)
How do I split this array into two arrays, one containing all the quacks; the other Aaaaarrrrrggggghhhhh?
Note that it won't always be in consecutive order, so was thinking maybe nested hashmaps, something like:
Check if (isset($myarr['$found_val']))
Append that array if found
Else create that place with a new array
But not sure how the arrays are implemented, so could be O(n) to append, in which case I'd need some other solution...
You can just group them based on values and store the keys
$array = array(0 => "quack","DOG" => "quack",1 => "quack","CAT" => "quack",2 => "Aaaaarrrrrggggghhhhh","CAERBANNOG" => "Aaaaarrrrrggggghhhhh");
$final = array();
foreach ( $array as $key => $value ) {
if (! array_key_exists($value, $final)) {
$final[$value] = array();
}
$final[$value][] = $key;
}
var_dump($final);
Output
array
'quack' =>
array
0 => int 0
1 => string 'DOG' (length=3)
2 => int 1
3 => string 'CAT' (length=3)
'Aaaaarrrrrggggghhhhh' =>
array
0 => int 2
1 => string 'CAERBANNOG' (length=10)
Try this
$quacks_arr = array_intersect($your_array, array('quack'));
$argh_arr = array_intersect($your_array, array('Aaaaarrrrrggggghhhhh'));
If you want to sort them, then just do ksort
ksort($quacks_arr);
ksort($argh_arr);
Just in case anyone wants to do this in a more of and odd way:
Updated with air4x's idea of using only a single item array, instead of array_fill(0,count($a),$v). Makes it's much more sensible.
$a = array(
0 => "quack",
"DOG" => "quack",
1 => "quack",
"CAT" => "quack",
2 => "Aaaaarrrrrggggghhhhh",
"CAERBANNOG" => "Aaaaarrrrrggggghhhhh"
);
$b = array();
foreach( array_unique(array_values($a)) as $v ) {
$b[$v] = array_intersect($a, array($v));
}
echo '<xmp>';
print_r($b);
Totally not optimal - difficult to read - but still interesting :)

Turn flat array into nested array

Just working on something and can't find a simple solution to this problem without just looping through the array with a foreach. Does anyone have a simple solution for this
I want to turn this
&array(4) {
["a"]=>int(0)
["b"]=>int(1)
["c"]=>int(2)
["d"]=>int(3)
}
Into this
array(1) {
["a"]=>
array(1) {
[0]=>
array(1) {
["b"]=>
array(1) {
[0]=>
array(1) {
["c"]=>
array(1) {
[0]=>
array(1) {
["d"]=> int(1) //this value does not matter
}
}
}
}
}
}
}
The values don't matter at all I just need the keys to run against a array_intersect_key_recursive function that I have.
EDIT : The array has changed after testing it needs to be nested as an array of an array
I don't know how this could possibly end up helping you, but it was a fun exercise nonetheless.
$newArray = array();
$last = &$newArray;
$array = array_reverse(array_keys($array));
while ($item = array_pop($array)) {
if (!is_array($last)) {
$last = array();
}
$last[$item] = array(array());
$last = &$last[$item][0];
}
NOTE: I made this answer with the int(1). You said the value is not important so I'm not going to bother changing it for now, but you would have to do a bit more work if the value was important (probably something like get the value from the original array with $item as the key).
Another approach using recursion:
function toNestedArray(array $array, $index = 0) {
$return = array();
if ($index < count($array)) {
$return[$array[$index]] = toNestedArray($array, ++$index);
}
return $return;
}
Usage Example:
$flatArray = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4);
$nestedArray = toNestedArray(array_keys($flatArray));
print_r($nestedArray);
Output:
Array
(
[a] => Array
(
[b] => Array
(
[c] => Array
(
[d] => Array
(
)
)
)
)
)

Filter out keys from multidimensional array

I have the following array:
array(2) {
[0] => array(4) {
["presentation_id"] => int(143)
["user_id"] => int(2)
["session_id"] => int(46)
["submission_id"] => int(190)
}
[1] => array(4) {
["presentation_id"] => int(144)
["user_id"] => int(2)
["session_id"] => int(46)
["submission_id"] => int(190)
}
What I want is to have an array consisting of just certain keys of this array, for example:
array(2) {
[0] => array(4) {
["presentation_id"] => int(143)
["user_id"] => int(2)
}
[1] => array(4) {
["presentation_id"] => int(144)
["user_id"] => int(2)
}
Any ideas?
$array = array_map(function ($arr) {
return array_intersect_key($arr, array_flip(array('presentation_id', 'user_id')));
}, $array);
Important to note that this syntax requires PHP 5.3+.
For other versions:
foreach ($array as &$arr) {
$arr = array_intersect_key($arr, array_flip(array('presentation_id', 'user_id')));
}
I'd suggest this over unsetting unwanted keys (as suggested by others) if you definitely want to restrict the array to certain elements. If you add more elements to the array in the future you won't need to update this code, but you'd have to unset more elements that you may not want.
Try:
$newArray = array_map(function ($innerArray) {
unset($innerArray['session_id'], $innerArray['submission_id'] /*, and so on*/);
return $innerArray;
}, $oldArray);
please use foreach and unset the key which you want to remove. Like
foreach($data as $key=> $row){
unset[$key] ["session_id"] ;
}

Categories