I have a array structure as shown below.
$arr = [ "level1" =>
["level2" =>
["level3" =>
[ "key1" => "value1",
"key2" => "value2",
]
]
],
[ "level2-A" =>
["level3-A" =>
[ "key1" => "value1-A",
"key2" => "value2-A",
]
]
],
"level2-B" => "value",
"level2-c" => "value",
];
Expected output is as below :
[ "level3" => "value2",
"level3-A" => "value2-A",
"level2-B" => "value",
];
I have tried using array_map_reduce, but I could fetch only till level2.
Use nested loops. Check whether each level is an array before trying to loop through it.
$result = [];
foreach ($arr as $key1 => $level1) {
if (is_array($level1)) {
foreach ($level1 as $key2 => $level2) {
if (is_array($level2)) {
foreach ($level2 as $key3 => $level3) {
foreach ($level3 as $value) {
// loop to the end of the array
}
$result[$key3] = $value;
}
}
}
}
else {
$result[$key1] = $level1;
}
}
The result of this is
Array
(
[level3] => value2
[level3-A] => value2-A
[level2-B] => value
[level2-c] => value
)
I don't know the logic that should prevent adding level2-c to the result.
Related
I have an array with fields
[
"house" => "30|30|30",
"street" => "first|second|third",
...
]
I want to get array
[
[
"house" => "30",
"street" => "first",
...
],
[
"house" => "30",
"street" => "second",
...
],
[
"house" => "30",
"street" => "third",
...
]
]
I know how I can solve this using PHP and loop, but maybe this problem has more beautiful solution
use zip
$data = [
"house" => "30|30|30",
"street" => "first|second|third",
];
$house = collect(explode('|',$data['house']));
$street = collect(explode('|',$data['street']));
$out = $house->zip($street);
$out->toarray();
Here's something I managed to do with tinker.
$original = [
"house" => "30|30|30",
"street" => "first|second|third",
];
$new = []; // technically not needed. data_set will instantiate the variable if it doesn't exist.
foreach ($original as $field => $values) {
foreach (explode('|', $values) as $index => $value) {
data_set($new, "$index.$field", $value);
}
}
/* dump($new)
[
[
"house" => "30",
"street" => "first",
],
[
"house" => "30",
"street" => "second",
],
[
"house" => "30",
"street" => "third",
],
]
*/
I tried using collections, but the main problem is the original array's length is not equal to the resulting array's length, so map operations don't really work. I suppose you can still use each though.
$new = []; // Since $new is used inside a Closure, it must be declared.
collect([
"house" => "30|30|30",
"street" => "first|second|third",
...
])
->map(fn($i) => collect(explode('|', $i))
->each(function ($values, $field) use (&$new) {
$values->each(function ($value, $index) use ($field, &$new) {
data_set($new, "$index.$field", $value);
});
});
$array = ["house" => "30|30|30","street" => "first |second| third"];
foreach($array as $key=> $values){
$explodeval = explode('|',$values);
for($i=0; $i<count($explodeval); $i++){
$newarray[$i][$key]= $explodeval[$i];
}
}
output:
Array
(
[0] => Array
(
[house] => 30
[street] => first
)
[1] => Array
(
[house] => 30
[street] => second
)
[2] => Array
(
[house] => 30
[street] => third
)
)
I have a problem calling an external API, Sendgrid, to validate email addresses, when I working on my package abkrim/sendgrid
The API client based on an (official) Sendgrid library for PHP (laravel), returns an element of the response with a float value. (Pay attention to the value score)
I call a one endpoint and get this body
{
"result": {
"email": "jhjhkjhkjhjhksdas3#gmail.com",
"verdict": "Risky",
"score": 0.06393,
"local": "jhjhkjhkjhjhksdas3",
"host": "gmail.com",
"checks": {
"domain": {
"has_valid_address_syntax": true,
"has_mx_or_a_record": true,
"is_suspected_disposable_address": false
},
"local_part": {
"is_suspected_role_address": false
},
"additional": {
"has_known_bounces": false,
"has_suspected_bounces": true
}
},
"ip_address": "0.0.0.0"
}
}
And convert to array
"result" => [
"email" => "jhjhkjhkjhjhksdas3#gmail.com",
"verdict" => "Risky",
"score" => 0.06393,0
"local" => "jhjhkjhkjhjhksdas3",
"host" => "gmail.com",
"checks" => [
"domain" => [
"has_valid_address_syntax" => true,
"has_mx_or_a_record" => true,
"is_suspected_disposable_address" => false,
],
"local_part" => [
"is_suspected_role_address" => false,
]
"additional" => [
"has_known_bounces" => false,
"has_suspected_bounces" => true,
],
],
],
"ip_address" => "0.0.0.0",
]
To execute a foreach in this array I need to do one thing since the score value is interpreted as two array elements, the normal one, that is score and its value, and another element with the key equal to 0 and the value equal to 0.
Testing
/** #test */
function underscored_array_is_converted_on_normal_array()
{
$array = [
"key1" => "value1",
"key2" => "value2"
"key3" => 0.9998,0
"upperkey1_subkey1_final__one__element" => true,
"upperkey1_subkey1_final__two__element" => false,
"key4" => "1.1.1.1",
];
$result = General::normalizeArray($array);
$this->assertArrayHasKey('upperkey1', $result);
}
Helper class and method
public static function normalizeArray(array $array): array
{
$new = [];
foreach ($array as $key => $value) {
if (($key == $value) && ($key == 0)) continue; // Work around for problem value float
$newkey = str_replace('#', '_', str_replace('_', '.', str_replace('__', '#', $key)));
$new[$newkey] = $value;
}
return Arr::undot($new);
}
If dump on my test $result get a value "key3" => 0.9998,0
If not use if (($key == $value) && ($key == 0)) continue; I get a new element on array, because score converts onto two elements, one for score and other for key 0, value 0.
That's is normal?
Exists any way for work with array with float values?
When applying print_r(json_decode($json, true)) to your json it returns:
Array
(
[result] => Array
(
[email] => jhjhkjhkjhjhksdas3#gmail.com
[verdict] => Risky
[score] => 0.06393
[local] => jhjhkjhkjhjhksdas3
...
There is no ,0 at the end.
In your testing example you did add ,0 to the end of key3. This part:
$array = [
"key1" => "value1",
"key2" => "value2",
"key3" => 0.9998,0,
"upperkey1_subkey1_final__one__element" => true,
Is similar to doing:
$array = [
"key1" => "value1",
"key2" => "value2",
"key3" => 0.9998,
0 => 0,
"upperkey1_subkey1_final__one__element" => true,
Your adding an element to the array without specifying the key, so PHP numerates it for you.
I have an array of this sort:
$array = [
"Darren" => [
"age" => "18",
"work" => [
"occupation" => "developer",
"company" => "ABC Ltd"
]
],
"John" => [
"age" => "24",
"work" => [
"occupation" => "developer",
"company" => "ABC Ltd",
"url" => "www.example.com"
],
]
]
And would like to merge the keys with a dot in between, depending on the array's hierachy:
"Darren.age"
"Darren.work.occupation"
"Darren.work.company"
...
The function that I made so far is
public function buildExpressionKey($array, $parentKey = null){
$expression = [];
foreach($array as $key=>$value){
if(is_array($value)){
array_push($expression, $parentKey. implode(".",
$this->buildExpressionKey($value, $key)));
}else{
array_push($expression, $key);
}
}
return $expression;
}
it is returning this value at the moment:
[
[0] => "age.Darrenoccupation.company"
[1] => "age.Johnoccupation.company.url"
]
Was wondering if it is possible to make a function which automatically does merges the keys like that, thanks in advance :)
What you are currently asking for:
<?php
$people =
[
'John' =>
[
'Occupation' => 'Developer',
'Age' => 18
],
'Darren' =>
[
'Occupation' => 'Manager',
'Age' => 40
]
];
foreach($people as $name => $value)
foreach($value as $k => $v)
$strings[] = $name . '.' . $k;
var_export($strings);
Output:
array (
0 => 'John.Occupation',
1 => 'John.Age',
2 => 'Darren.Occupation',
3 => 'Darren.Age',
)
Managed to resolve this issue :)
/**
* #param $array
* #return array
*/
public function buildExpressionKey($array){
$iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array));
$keys = array();
foreach ($iterator as $key => $value) {
// Build long key name based on parent keys
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$key = $iterator->getSubIterator($i)->key() . '.' . $key;
}
$keys[] = $key;
}
return $keys;
}
Found something similar on here: Get array's key recursively and create underscore separated string
I want to get calleridnum without using array . Is this possible?
or is there other way to do this ?
I have this code :
$participants = [
[ 'calleridnum' => 1,
'test' => 'yay'
],
[ 'calleridnum' => 2,
'test' => 'yay'
],
[ 'calleridnum' => 3,
'test' => 'yay'
]
];
$conferance_participants = [
[ 'uid' => 1,
'test' => 'yay2',
'dit' => 'deze'
],
[ 'uid' => 2,
'test' => 'test',
'dit' => 'wew'
]
];
foreach ($participants as $key=>$p) {
foreach ($conferance_participants as $key=>$cp) {
if ($p['calleridnum'] == $cp['uid']) {
$calleridnum[] = $p['calleridnum'];
}
}
}
print_r( $calleridnum );
My output is:
Array ( [0] => 1 [1] => 2 )
but I want the output to be like this
1,2
Use implode() outside of foreach loop
echo $str = implode (",", $calleridnum);
Try this: Implode your array to be converted into string.
$calleridnum= [];
foreach ($participants as $key=>$p) {
foreach ($conferance_participants as $key=>$cp) {
if ($p['calleridnum'] == $cp['uid']) {
$calleridnum[] = $p['calleridnum'];
}
}
}
$result = implode(',', $calleridnum);
echo $result;
I'll simply use array_intersect,array_column along with implode as
echo implode(',', array_intersect(array_column($conferance_participants,'uid'), array_column($participants,'calleridnum')));
Demo
$main_array= array(
"Key1" => array(1,2,14,15,16,17,18,19,22,45,47),
"Key2" => array(6,7,40,41,42,43,48,51,52),
"Key3" => array(4,5,8,46,49,53),
"Key4" => array(3,12,13,50),
"Key5" => array(0,9,10,11,20,23,44,),
"Key6" => array(21,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,55,56,57),
"Key7" => array(53)
);
Could you point me how can I get the KeyX value ?
Desired command $getKey(53) - 53 is in the Key7
Try something like this:
foreach ($main_array as $key => $value) {
if(is_array($value) && array_search($search, $value) !== false) {
return $key;
}
}