array function to create new array with values as being the keys? - php

I have an array:
$ids = array(1 => '3010', 2 => '10485', 3 => '5291');
I want to create a new array that takes the values of the $ids array and sets them as the keys of a new array, having the same value.
The final array would be:
$final = array('3010' => 'Green', '10485' => 'Green', '5291' => 'Green');
This will be used in apc_add().
I know I can accomplish this by looping thru it.
$final = array();
foreach($ids as $key => $value):
$final[$value] = 'Green';
endforeach;
But I was wondering if there was php function that does this without having to use a forloop, thanks!

You are looking for array_fill_keys.
$final = array_fill_keys($ids, "Green");
However, be aware that strings that are decimal representations of integers are actually converted to integers when used as array keys. This means that in your example the numbers that end up as keys in $final will have been transformed to integers. Most likely won't make a difference in practice, but you should know about it.

You can do with array_fill_keys this way:
$final = array_fill_keys($ids, "Green");

Related

Adding elements to array as sub-elements dynamically in PHP [duplicate]

This question already has answers here:
Using a string path to set nested array data [duplicate]
(8 answers)
Closed 2 years ago.
I want to find a workaround for the following problem:
I have n vectors(unique), like the following: ("val1", "val2", "val3", ..., "valn" ).
Each vector's length is different.
I want to add any of those in a new array, but using the vector values(val1,val2,val3) elements as sub-elements recursively for the new array, taken from the main vector(val1 => val+1 => val+2 => val+3 => ... val+n => solution), and the last element of the vector is an integer or a string(not a sub-array/vector as the others), which will match with the last element of the new array, and it's new array's soluton/target.
The workaround solution I am applying right now is this:
Let's suppose the target(solution) is the end value of the array(an integer or string).
In this case I suppose to work on a vector with 4 elements, where the last one is the solution.
$vector = array("val1", "val2", "val3", "target");
$count = count($vector);
$new_array = array();
switch($count){
case 1:
....
case 4:
$new_array[$vector[0]][$vector[1]][$vector[2]] = $vector[3];
/*New array will be
$new_array = [
val1 =>
val2 =>
val3 => "target"
];
*/
break;
}
The vectors I am using are many and with different sizes, so the solution/target can be in the 1st element, second, third and so on, so I applied in my switch any cases from 0 to 5 for example, working as wrote above.
I think there could be a better solution, to loop inside a for(or better, a while) cycle
But I am currently having no ideas on how it should be, and I didn't find any workaround in the web.
Does anyone have a soluton for this?
Thanks in advance
You can build the resulting array starting from the most recent nested element:
$vector = array("val1", "val2", "val3", "val4", "val5", "target");
$new_array = array_pop($vector);
foreach(array_reverse($vector) as $val) {
$new_array = [$val => $new_array];
}
print_r($new_array);
Hi You can change your code like it:
<?php
$vector = array("val1", "val2", "val3", "val4", "val5", "target");
$count = count($vector);
$new_array = array();
$new_array[$vector[$count - 2]] = $vector[$count - 1];
for ($i=($count - 3); $i >= 0; $i--) {
$temp_array = array();
$temp_array[$vector[$i]] = $new_array;
$new_array = $temp_array;
}
print_r($new_array);
And the result will be like it:
Array
(
[val1] => Array
(
[val2] => Array
(
[val3] => Array
(
[val4] => Array
(
[val5] => target
)
)
)
)
)

json_decode - Force array keys to be string

Take a look at the following code:
$a = json_decode('{"0":"xy"}', true);
This will return an associative array like [0 => "xy"].
Is there a way not to automatically convert the keys to numbers? The result I'd like to have would be the array ["0" => "xy"] with strings as keys exclusively.
First decode it as an object (without true parameter) and then typecast it as array:
$a = (array) json_decode('{"0":"xy"}');
var_dump($a);
Ouput:
array (size=1)
'0' => string 'xy' (length=2)
Not really sure why you would want numerical array keys to be strings. It can make life harder when trying to search through an array by key or rekey the array.
However, if you really want your keys to be strings this should help
$array = json_decode('{"0":"xy"}', true);
foreach($array as $key => $value) {
$newArray[(string) $key] = $value;
}

Building a new array using key IDS

Using the numbers from $ids, I want to pull the data from $nuts.
So for example:
$ids = [0,3,5]; // 0 calories, 3 sugar, 5 fat
$nuts = [
'calories' => 'cal',
'protein' => 'pro',
'carbohydrate' => 'car',
'sugar' => 'sug',
'fiber' => 'fib',
'fat' => 'fat',
];
$returnData = [
'calories' => 'cal',
'sugar' => 'sug',
'fat' => 'fat',
];
I could loop through each $ids number with a foreach(); but I'm curious to see if there is a better method than this?
$newNuts = array_values(array_flip($nuts));
foreach($ids as $i)
$returnData[$newNuts[$i]] = $nuts[$newNuts[$i]];
I did some work and realized, you don't need array_flip, array_values is fine.
$num_nuts = array_values ($nuts);
for ($z=0; $z<sizeof($ids); $z++) {
echo $num_nuts[$ids[$z]];
}
Just 1 more line of code, but I think it does the job. I think mine is going to be faster because the array_flip basically exchanges all keys with their associated values in an array, which is not what I am doing. It's actually one less pain.
I am simply converting the original array to a new one by index and simply looping upon it. Also, not the elegant way to use the power of PHP available to us, but works just fine. array_flip is O(n), but I think better not use it for larger data-sets.
How about a simple array_slice?
$result = array();
foreach ($ids as $i) {
$result += array_slice($nuts, $i, 1, true);
}
No need to create a copy of the array.

Remove blacklist keys from array in PHP

I have an associative array of data and I have an array of keys I would like to remove from that array (while keeping the remaining keys in original order -- not that this is likely to be a constraint).
I am looking for a one liner of php to do this.
I already know how I could loop through the arrays but it seems there should be some array_map with unset or array_filter solution just outside of my grasp.
I have searched around for a bit but found nothing too concise.
To be clear this is the problem to do in one line:
//have this example associative array of data
$data = array(
'blue' => 43,
'red' => 87,
'purple' => 130,
'green' => 12,
'yellow' => 31
);
//and this array of keys to remove
$bad_keys = array(
'purple',
'yellow'
);
//some one liner here and then $data will only have the keys blue, red, green
$out =array_diff_key($data,array_flip($bad_keys));
All I did was look through the list of Array functions until I found the one I needed (_diff_key).
The solution is indeed the one provided by Niet the Dark Absol. I would like to provide another similar solution for anyone who is after similar thing, but this one uses a whitelist instead of a blacklist:
$whitelist = array( 'good_key1', 'good_key2', ... );
$output = array_intersect_key( $data, array_flip( $whitelist ) );
Which will preserve keys from $whitelist array and remove the rest.
This is a blacklisting function I created for associative arrays.
if(!function_exists('array_blacklist_assoc')){
/**
* Returns an array containing all the entries from array1 whose keys are not present in any of the other arrays when using their values as keys.
* #param array $array1 The array to compare from
* #param array $array2 The array to compare against
* #return array $array2,... More arrays to compare against
*/
function array_blacklist_assoc(Array $array1, Array $array2) {
if(func_num_args() > 2){
$args = func_get_args();
array_shift($args);
$array2 = call_user_func_array('array_merge', $args);
}
return array_diff_key($array1, array_flip($array2));
}
}
$sanitized_data = array_blacklist_assoc($data, $bad_keys);

How to find the indices of duplicate values in an array

I have two arrays, array1 and array2 that I am using to populate a table, so that array1[5] and array2[5] both fill the same row but I want to write a function that removes both array1[i] and array2[i] if array1[i] is a duplicate of array1[j] for some j less than i, where i is an arbitrary positive integer.
To accomplish this I was to work out the indices of duplicate values in array1 and then use this information to delete the entries from both array1 and array2 for these indices, before populating my table.
Any ideas gratefully received.
Thanks.
The array_unique function removes dupes, but preserves keys. Then you can just iterate through the other array and remove the keys that don't exist in the first one.
$array1 = array_unique($array1);
foreach ($array2 as $key => $val) {
if (!array_key_exists($key,$array1)) unset($array2[$key]);
}
$array1_keys = array_keys($array1); // all keys
$unique = array_keys(array_unique($array1)); // keys of unique values
$duplicate = array_diff($array1_keys, $unique_keys); // keys of the duplicate values
foreach($duplicate as $key){
unset($array2[$key]);
}
Sidenote: Be aware that array_diff uses string casting for comparison. If your array contains non scalar values you should have a look at array_udiff.
Edit: Mingos post in my eyes did not fully suit the question, looks like i was wrong :D
If your array keys are meaningful and not just a 0-based index and you want to keep the duplicate entry with the lowest key (as you indicate might be the case from your question) then you need to sort the array first. If you don't, you will get the first entry in the array for each duplicate value and not entry with the lowest key. Compare
$array = array( 5 => 'foo', 1 => 'bar', 2 => 'foo', 3 => 'bar' );
$array = array_unique( $array );
var_dump( $array );
with
$array = array( 5 => 'foo', 1 => 'bar', 2 => 'foo', 3 => 'bar' );
ksort( $array );
$array = array_unique( $array );
var_dump( $array );
In asociative arrays, you can get easily a counter of item to detect repeated and the first ocurrence with something as simple as (in this case using an associative array, where $array_key is the key to count) using array_count_values:
$index = null;
$array_by_columns = array_count_values(array_column($associative_array, $array_key);
foreach($array_by_columns) as $key => $ocurrences){
if($ocurrences > 1){
$index = $key;
}
}
If you have $index there are repeated element and also is the index of in the array.
A more compacted way in a line:
$index = null;
foreach(array_count_values(array_column($associative_array, $array_key)) as $key => $ocurrences)if($ocurrences > 1) $index = $key;
Data example:
[ARRAY] (start)
n0
KEY = 0
VALUE = {"user":"1","points":"10"}
n1
KEY = 1
VALUE = {"user":"4","points":"10"}
n2
KEY = 2
VALUE = {"user":"5","points":"30"}
n3
KEY = 3
VALUE = {"user":"1","points":"40"}
[ARRAY] (end)
More info:
array_count_values
array_column

Categories