php array re populate keys - php

Hi I have an array, I need to change the keys, in an orderly manner but don't change the order the values are. e.g.
$a = array (
0=>'h',
1=>'blabla',
2=>'yes'
);
I used
unset($a[1]);
but i need the key to restart calculating the keys
0,1,2 ... etccc
so i don't end up with:
array(
0 => 'h',
2 => 'yes'
)
but it should come return:
array(
0 => 'h',
1 => 'yes'
)

You need to apply array_values on your array to re-index.
$a = array_values($a);
Bonus: If you also need to order your values you can use sort and it too will re-index your array.
Note: By using any of array_values or sort you will loose any string keys you may have.

Call array_values on it:
$a = array (
0=>'h',
1=>'blabla',
2=>'yes'
);
unset($a[1]);
$a = array_values($a);
var_dump($a);
/*
array(2) {
[0]=>
string(1) "h"
[1]=>
string(3) "yes"
}
*/

You can also use array_splice() instead of unset(), which will automatically reindex the array elements:
$a = array (
0=>'h',
1=>'blabla',
2=>'yes'
);
array_splice($a,1,1);
var_dump($a);

Related

PHP only get values from multidimensional array where keys intersect with other array

I think this should be something simple, but I can't find a way to do it.
I have two arrays, one with colors and ids
$color_ids = [
'green' => [1,2,3],
'blue' => [4,5],
'red' => [6],
'pink' => [7,8,9],
'yellow' => [10]
];
and others with selection.
$select = ['green', 'red', 'yellow'];
Then I need the ids where intersects keys between $color_ids and $select. This should be the result (a simple linear array):
$results = [1,2,3,6,10];
I've tried this:
$result = array_values(array_intersect_key( $color_ids, array_flip($select ) ) );;
But I get multidimensional array:
array(3) {
[0]=> array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
[1]=> array(1) { [0]=> int(6) }
[2]=> array(1) { [0]=> int(10) }
}
I get the same result with this:
$result = [];
foreach ($select as $key) {
if (isset($color_ids[$key]))
$result[] = $color_ids[$key];
}
How can I get a simple linear array with ids?
1) Iterate over the key array
2) Merge all the arrays into one using array_merge
$select = ['green', 'red', 'yellow'];
$finalArray=[];
foreach($select as $value){
$finalArray= array_merge($finalArray,$color_ids[$value]);
}
echo "<pre>";
print_r($finalArray);
Output:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 6
[4] => 10
)
You can use array_merge with the ... operator which is a common flattening technique demonstrated here.
array_merge(...$result);
Array Merge documentation.
Splat Operator documentation.
with foreach
$result = [];
foreach($color_ids as $color => $ids){
$result = array_merge($result, in_array($color, $select) ? $ids : []);
}
If you are looking for a fully "functional style" solution, here's one.
Set up your filtering array ($select) so that it has keys like the master array's keys. In other words, flip the values into keys.
Then swiftly filter the master array using array_intersect_key().
Then to flatten the remaining data, prepend the splat/spread operator and call array_merge().
Until you are on a php version that allows associative arrays to be spread, then you'll need to call array_values() to reindex the first level keys so that the spread operator doesn't choke.
Code: (Demo)
var_export(
array_merge(
...array_values(
array_intersect_key(
$color_ids,
array_flip($select)
)
)
)
);
Or if you prefer jumble the syntax into a single line:
var_export(array_merge(...array_values(array_intersect_key($color_ids, array_flip($select)))));
Although a foreach() may perform a few nanoseconds faster than functional programming, you are never going to notice on such small data sets. One benefit of this coding style is that you don't have to name any temporary variables to push qualifying data into. In other words you can feed this directly into a return statement inside of a function which I find to be very tidy.
Alternatively, if you don't mind generating a result variable, then iterated array_push() calls while spreading the matching nominated color_id value is pretty simple. This technique is different in that if $select contains a color that is not a key in $color_id, then php will bark at you!
Code: (Demo)
$result = [];
foreach ($select as $color) {
array_push($result, ...$color_ids[$color]);
}
var_export($result);
Both techniques offer the same result.

Sorting an array by the values of another array

I have a some messy data coming in from a feed, and am trying to figure out how to sort it correctly. I posted a simplified example below. I'd like to sort the people array alphabetically by the Group name.
$people = array(
"category_id_1" => array (
"Mark",
"Jenny",
"Andrew"
),
"category_id_2" => array (
"John",
"Lewis",
"Andrea"
),
"category_id_3" => array (
"Hannah",
"Angie",
"Raleigh"
)
);
$categories = array(
"category_id_1" => "Group B",
"category_id_2" => "Group C",
"category_id_3" => "Group A"
);
Ideally, the end result would be
$people = array(
"category_id_3" => array ( // Group A
"Hannah",
"Angie",
"Raleigh"
),
"category_id_1" => array ( // Group B
"Mark",
"Jenny",
"Andrew"
),
"category_id_2" => array ( // Group C
"John",
"Lewis",
"Andrea"
)
);
I've been spinning my wheels for a while now, and the closest I have gotten is this uasort, which still isn't doing the trick.
uasort($people, function ($a, $b) {
return strcmp($categories[$a], $categories[$b]);
});
Thanks so much for any help.
This can be achieved in a simpler way by taking advantage of array_replace:
// Work on a copy just to be sure the rest of your code is not affected
$temp_categories = $categories;
// Sort categories by name
asort($temp_categories);
// Replace the values of the sorted array with the ones in $people
$ordered_people = array_replace($temp_categories, $people);
You want to sort $people by its keys not its values. You can use uksort for this. Additionally you need to make $categories available in your function. I prefer use for that; but you could also make it a global variable. Final code:
uksort($people, function ($a,$b) use ($categories) {
return strcmp($categories[$a], $categories[$b]);
});
Manual for uksort
use language construct. Before example 3.
I think what you need is to Asort categories and the use that sorted array in a foreach.
Asort($categories);
Foreach($categories as $key => $group){
$new[$key] =$people[$key];
}
Var_dump($new);
https://3v4l.org/kDAQW
Output:
array(3) {
["category_id_3"]=> array(3) {
[0]=> "Hannah"
[1]=> "Angie"
[2]=> "Raleigh"
}
["category_id_1"]=> array(3) {
[0]=> "Mark"
[1]=> "Jenny"
[2]=> "Andrew"
}
["category_id_2"]=>array(3) {
[0]=> "John"
[1]=> "Lewis"
[2]=> "Andrea"
}
}
Try this(tested and working):
asort($categories);
$sorted = array();
foreach ($categories as $key => $value)
$sorted[$key]=$people[$key];
A better shorter approach:(tested and working)
asort($categories);
$result = array_merge($categories,$people);
The second method takes advantage of the fact that array_merge function replace the values in the first array with those in the second one when keys are the same.
warning : The second approach will not work if the keys are numbers. Use only string keys with it. Furthermore if the categories array has entries without corresponding entries in the people array they will be copied to the result
To solve this problem we use array_replace :
asort($categories);
$result = array_replace($categories,$people);
Var_dump($result);// tested and working

Strange behavior of Array count()

I have following Array
$arr = array(1 => 1, "1" => 50);
When I execute count() on it, it gives me strange answer: 1
echo count($arr);
Whereas an array $arr has two elements.
Why?
It is due to Type Casting . Check Example #2 Type Casting and Overwriting example in Arrays .
If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten .
$arr = array(1 => 10, "1" => 20);
var_dump( $arr );
Displays :
array (size=1)
1 => int 20
And so :
echo count( $arr );
Displays :
1
Which is correct .
If multiple elements in the array declaration use the same key, only the last one will be used as all others are overwritten.As all the keys in the below example are cast to 1, the value will be overwritten on every new element.
Sample Code:
$array = array(
1 => "a",
"1" => "b"
);
var_dump($array);
echo count($array);
Sample output:
array(1) {
[1]=>
string(1) "b"
}
1
For details have a look here:http://nz1.php.net/manual/en/language.types.array.php
if you change the "1" to "2" it will count 2. The problem is the fact that you choose the first element in the array to be 1 then you choose it to be 50, so in the final, the array will have one element, which is 50.
See it here!

PHP combine two associative arrays into one array

$array1 = array("$name1" => "$id1");
$array2 = array("$name2" => "$id2", "$name3" => "$id3");
I need a new array combining all together, i.e. it would be
$array3 = array("$name1" => "$id1", "$name2" => "$id2", "$name3" => "$id3");
What is the best way to do this?
Sorry, I forgot, the ids will never match each other, but technically the names could, yet would not be likely, and they all need to be listed in one array. I looked at array_merge but wasn't sure if that was best way to do this. Also, how would you unit test this?
array_merge() is more efficient but there are a couple of options:
$array1 = array("id1" => "value1");
$array2 = array("id2" => "value2", "id3" => "value3", "id4" => "value4");
$array3 = array_merge($array1, $array2/*, $arrayN, $arrayN*/);
$array4 = $array1 + $array2;
echo '<pre>';
var_dump($array3);
var_dump($array4);
echo '</pre>';
// Results:
array(4) {
["id1"]=>
string(6) "value1"
["id2"]=>
string(6) "value2"
["id3"]=>
string(6) "value3"
["id4"]=>
string(6) "value4"
}
array(4) {
["id1"]=>
string(6) "value1"
["id2"]=>
string(6) "value2"
["id3"]=>
string(6) "value3"
["id4"]=>
string(6) "value4"
}
Check out array_merge().
$array3 = array_merge($array1, $array2);
There is also array_replace, where an original array is modified by other arrays preserving the key => value association without creating duplicate keys.
Same keys on other arrays will cause values to overwrite the original array
New keys on other arrays will be created on the original array
I use a wrapper around array_merge to deal with SeanWM's comment about null arrays; I also sometimes want to get rid of duplicates. I'm also generally wanting to merge one array into another, as opposed to creating a new array. This ends up as:
/**
* Merge two arrays - but if one is blank or not an array, return the other.
* #param $a array First array, into which the second array will be merged
* #param $b array Second array, with the data to be merged
* #param $unique boolean If true, remove duplicate values before returning
*/
function arrayMerge(&$a, $b, $unique = false) {
if (empty($b)) {
return; // No changes to be made to $a
}
if (empty($a)) {
$a = $b;
return;
}
$a = array_merge($a, $b);
if ($unique) {
$a = array_unique($a);
}
}
$array = array(
22 => true,
25 => true,
34 => true,
35 => true,
);
print_r(
array_replace($array, [
22 => true,
42 => true,
])
);
print_r(
array_merge($array, [
22 => true,
42 => true,
])
);
If it is numeric but not sequential associative array, you need to use array_replace
UPDATE
Just a quick note, as I can see this looks really stupid, and it has no good use with pure PHP because the array_merge just works there. BUT try it with the PHP MongoDB driver before you rush to downvote. That dude WILL add indexes for whatever reason, and WILL ruin the merged object. With my naïve little function, the merge comes out exactly the way it was supposed to with a traditional array_merge.
I know it's an old question but I'd like to add one more case I had recently with MongoDB driver queries and none of array_merge, array_replace nor array_push worked. I had a bit complex structure of objects wrapped as arrays in array:
$a = [
["a" => [1, "a2"]],
["b" => ["b1", 2]]
];
$t = [
["c" => ["c1", "c2"]],
["b" => ["b1", 2]]
];
And I needed to merge them keeping the same structure like this:
$merged = [
["a" => [1, "a2"]],
["b" => ["b1", 2]],
["c" => ["c1", "c2"]],
["b" => ["b1", 2]]
];
The best solution I came up with was this:
public static function glueArrays($arr1, $arr2) {
// merges TWO (2) arrays without adding indexing.
$myArr = $arr1;
foreach ($arr2 as $arrayItem) {
$myArr[] = $arrayItem;
}
return $myArr;
}
I stumbled upon this question trying to identify a clean way to join two assoc arrays.
I was trying to join two different tables that didn't have relationships to each other.
This is what I came up with for PDO Query joining two Tables. Samuel Cook is what identified a solution for me with the array_merge() +1 to him.
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM ".databaseTbl_Residential_Prospects."";
$ResidentialData = $pdo->prepare($sql);
$ResidentialData->execute(array($lapi));
$ResidentialProspects = $ResidentialData->fetchAll(PDO::FETCH_ASSOC);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM ".databaseTbl_Commercial_Prospects."";
$CommercialData = $pdo->prepare($sql);
$CommercialData->execute(array($lapi));
$CommercialProspects = $CommercialData->fetchAll(PDO::FETCH_ASSOC);
$Prospects = array_merge($ResidentialProspects,$CommercialProspects);
echo '<pre>';
var_dump($Prospects);
echo '</pre>';
Maybe this will help someone else out.
For me, this small snippet worked.
I have similar structures for both my arrays except the keys are a little different.
e.g
JSON 1 : {"sketchCount":{"2":{"A":50477}},"raw":{"2":{"A":70477}}}
JSON 2 : {"sketchCount":{"2":{"B":50477}},"raw":{"2":{"B":50477}}}
Desired Output JSON : {"sketchCount":{"2":{"A":70477,"B":50477}},"raw":{"2":{"A":70477,"B":50477}}}
Code
foreach($existingArray as $key => $possibleArray){
if(is_array($possibleArray)){
foreach($possibleArray as $index=> $value){
$combinedArray[$key][$index] = $value;
if(array_key_exists($key,$newArray) && array_key_exists($index,$newArray[$key])){
foreach($newArray[$key][$index] as $newKey=> $associatedValue){
$combinedArray[$key][$index][$newKey] = $associatedValue;
}
}
}
}
}

What is the reverse of (object) array (key => value) in PHP?

Is there a fast way to return a key when you know its value in PHP?
For example, if you have:
$Numbers = (object) array ( "0" => 0, "1" => 1, "2" => 3, "3" => 7, "4" => 13 );
is there a way to return:
echo re(13); // Print 4
One way I could think of is to build a function specifically for this, but I was wondering if there is a better way.
There is array_search:
$key = array_search(13, (array) $Numbers);
See http://ua2.php.net/array_search
As several other people have mentioned, array_search does what you asked. But if you want an array of ALL the keys that contain the value instead of only the first, you can use array_keys.
print_r(array_keys($Numbers, 13)); // print Array ( [0] => 4 )
http://www.php.net/manual/en/function.array-keys.php
if you are certain that you have unique keys:
$flipped = array_flip($array);
$key = $flipped[$knownValue];
return $key;
Otherwise, use array_search:
return array_search($knownValue, $array);
The first approach may be better if you do a number of lookups, and have unique values. The second approach returns the first matching key in case of multiple values.
http://php.net/array_search
echo array_search($valToSearch, (array) $Numbers);
http://php.net/manual/en/function.array-search.php

Categories