php - recreate array? - php

I've "inherited" some data, which I'm trying to clean up. The array is from a database which, apparently, had no keys.
The array itself, is pretty long, so I'm simplifying things for this post...
[0] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[ename] => Standard
[eaction] => Check
)
[1] => Array
(
[id] => 2
[uid] => 110
[eid] => 8
[ename] => Standard
[eaction] => Check
)
[2] => Array
(
[id] => 2
[uid] => 200
[eid] => 8
[ename] => Standard
[eaction] => Check
)
I'm trying to shift things around so the array is multidimensional and is grouped by ename:
[0] => Array
(
[Standard] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[eaction] => Check
)
)
[0] => Array
(
[Standard] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[eaction] => Check
)
)
[0] => Array
(
[Standard] => Array
(
[id] => 2
[uid] => 130
[eid] => 8
[eaction] => Check
)
)
Anyone know how to do something like this?

You can use usort() to sort an array by a user-defined function. That function could compare the ename fields. Then it's just a simple transformation. Like:
usort($array, 'cmp_ename');
function cmp_ename($a, $b) {
return strcmp($a['ename'], $b['ename']);
}
and then:
$output = array();
foreach ($array as $v) {
$ename = $v['ename'];
unset($v['ename']);
$output[] = array($ename => $v);
}

$outputarray = array();
foreach($inputarray as $value) {
$outputarray[] = array($value['ename'] => $value);
}
would accomplish what your examples seem to indicate (aside from the fact that your 'result' example has multiple things all with key 0... which isn't valid. I'm assuming you meant to number them 0,1,2 et cetera). However, I have to wonder what benefit you're getting from this, since all it appears to be doing is adding another dimension that serves no purpose. Perhaps you could clarify your example if there are other things to take into account?

$outputarray = array();
foreach($inputarray as &$value) {
$outputarray[][$value['ename']] = $value;
unset($value['ename']);
} unset($value);

I'm guessing that this is what you're asking for:
function array_group_by($input, $field) {
$out = array();
foreach ($input as $row) {
if (!isset($out[$row[$field]])) {
$out[$row[$field]] = array();
}
$out[$row[$field]][] = $row;
}
return $out;
}
And usage:
var_dump(array_group_by($input, 'ename'));

philfreo was right but he was also off a little. with his code every time you encounter an array element with an ['ename'] the same as one you've already gone through it will overwrite the data from the previous element with the same ['ename']
you might want to do something like this:
$output = array();
foreach ($YOURARRAY as $value) {
$output[$value['ename']][] = $value;
}
var_dump($output); // to check out what you get

Related

get specific array in a multi-dimentional array on php

I have the following structure of an array which is decoded from a JSON object. From this array result I need to fork widgets for processing. It is an unstable JSON array so the parent keys may differs in future but the widgets will not.
(
[2] => Array
(
[MA] => Array
(
[0] => Array
(
[activities] => Array
(
[0] => Array
(
[activity_id] => 3
[activity_name] => Excavation
[activity_unique_id] => EXCAV-d435
[created_date] => 2021-02-08 21:42:53
[end_date] => 2021-02-08 21:42:08
[fk_client_id] => 1
[fk_main_activity] => 3
[fk_project_id] => 2
[relation_type] => MA-A-SA-W
[start_date] => 2021-02-08 21:42:08
[widgets] => Array
(
[0] => Array
(
[activity_mapping] => STRUC-be4c
[check_box_val] => 0
[checkbox_unique_id] => EXCAV-dceae
[checkbox_widget_id] => 5
[created_date] => 2021-02-08 21:43:12
)
)
)
)
[created_date] => 2021-02-08 21:42:44
[end_date] => 2021-02-08 21:42:08
[fk_client_id] => 1
[fk_floor_ids] => 7
[fk_project_id] => 2
[main_activity_id] => 3
[main_activity_name] => Structure MA1
[main_activity_unique_id] => STRUC-be4c
[relation_type] => MA-A-SA-W
[sequence_no] => 1
[start_date] => 2021-02-08 21:42:08
[tower_ids] => 4
[widgets_ids] =>
)
...
it is a big source So I cut shorted it. From the above result set I only need to fork the following widgets object.
[widgets] => Array
(
[0] => Array
(
[activity_mapping] => STRUC-be4c
[check_box_val] => 0
[checkbox_unique_id] => EXCAV-dceae
[checkbox_widget_id] => 5
[created_date] => 2021-02-08 21:43:12
)
)
)
Thanks in advance.
This recursive function searches for the first occurrence of a key in a multidimensional array and returns its value.
function array_find_key(array $array, $key) {
if (array_key_exists($key, $array)) {
return [$key => $array[$key]];
} else {
foreach($array as $item) {
if (is_array($item) && $result = array_find_key($item, $key)) {
return $result;
}
}
}
}
$result = array_find_key($array, 'widgets');
fiddle
The answer from #id'7238 is designed to search for a qualifying value in the current level before attempting to traverse a deeper level. The nuance in my answer (which does not call array_key_exists()) is that it checks keys as it traverses a level and will go down a level as soon as a non-qualifying subarray is encountered.
While looping, if the key is found, the payload is returned (and potentially passed up the recursive stack). If a value is array type data, then the next level down is processed -- if that level contains a qualifying key, it is passed up the stack.
If there are no qualifying keys in the input array, then null will be returned.
Code: (Demo)
function searchByKey(array $array, $find) {
foreach($array as $k => $v) {
if ($k === $find) {
return [$k => $v];
}
if (is_array($v)) {
$result = searchByKey($v, $find);
if ($result) {
return $result;
}
}
}
}
var_export(searchByKey($a, 'foo'));
For fun, if the nesting level will be the same just with the keys being different, this will give you the widgets array:
$result = current(current(current(current(current($array)))))['widgets'];
This will give you the array under the widgets array:
$result = current(current(current(current(current(current($array)))))['widgets']);
The first example will only work if the widgets array is 5 levels deep in the array and for the second if there is only 1 array under widgets (if there are more you will get the first).

Getting all values from a specific array within a multidimentional array

I've been searching around quite a bit for an answer for this, but I'm afraid that I've been unable to figure out a solution to this problem. I've created a multidimensional array which includes zip code information. However, I've been unable to pull the values out of it in the way that I need to. Here's an example of the print_r():
Array (
[0] => Array (
[0] => 59101
[1] => 0.0 )
[1] => Array (
[0] => 59102
[1] => 5.0 )
[2] => Array (
[0] => 59105
[1] => 6.8 )
[3] => Array (
[0] => 59106
[1] => 9.2 )
[4] => Array (
[0] => 59037
[1] => 12.7 )
[5] => Array (
[0] => 59044
[1] => 13.9 )
[6] => Array (
[0] => 59002
[1] => 16.6 )
[7] => Array (
[0] => 59079
[1] => 19.3 )
)
I need to look through the array for a specific zip code, and then get distance (the second value in each array) associated with that zip code. I'd considered restructuring the array, but I'm unsure of how to accomplish it. Here's my current code:
EDIT## sorry, I may not have been clear. The below code is what I'm using to build the array, not to extract information from the array. I have not idea how to get the information out of the array.
$rArray = array();
foreach ($points as $point){
$zips = $point->Postcode;
$dists = number_format($point->D,1);
array_push($rArray,array($zips,$dists));
}
Any thoughts on the best way to accomplish this? Thanks!
This?
EDIT: After your question update.
function getDistanceByZip($zip) {
$array = //your array here;
foreach($array as $value) {
if($zip == $value[0]) {
return $value[1];
}
}
return false;
}
Maybe this?
foreach ($points as $point){
if ($point->Postcode === $codeIamLookingFor) {
echo "Distance: " . number_format($point->D, 1);
}
}
function arrayseek($array, $zip){
foreach($array as $k => $v){
if($v[0] == $zip){
return $v[1];
}
}
return false;
}

Checking if array value exists in a PHP multidimensional array

I have the following multidimensional array:
Array ( [0] => Array
( [id] => 1
[name] => Jonah
[points] => 27 )
[1] => Array
( [id] => 2
[name] => Mark
[points] => 34 )
)
I'm currently using a foreach loop to extract the values from the array:
foreach ($result as $key => $sub)
{
...
}
But I was wondering how do I see whether a value within the array already exists.
So for example if I wanted to add another set to the array, but the id is 1 (so the person is Jonah) and their score is 5, can I add the 5 to the already created array value in id 0 instead of creating a new array value?
So after the loop has finished the array will look like this:
Array ( [0] => Array
( [id] => 1
[name] => Jonah
[points] => 32 )
[1] => Array
( [id] => 2
[name] => Mark
[points] => 34 )
)
What about looping over your array, checking for each item if it's id is the one you're looking for ?
$found = false;
foreach ($your_array as $key => $data) {
if ($data['id'] == $the_id_youre_lloking_for) {
// The item has been found => add the new points to the existing ones
$data['points'] += $the_number_of_points;
$found = true;
break; // no need to loop anymore, as we have found the item => exit the loop
}
}
if ($found === false) {
// The id you were looking for has not been found,
// which means the corresponding item is not already present in your array
// => Add a new item to the array
}
you can first store the array with index equal to the id.
for example :
$arr =Array ( [0] => Array
( [id] => 1
[name] => Jonah
[points] => 27 )
[1] => Array
( [id] => 2
[name] => Mark
[points] => 34 )
);
$new = array();
foreach($arr as $value){
$new[$value['id']] = $value;
}
//So now you can check the array $new for if the key exists already
if(array_key_exists(1, $new)){
$new[1]['points'] = 32;
}
Even though the question is answered, I wanted to post my answer. Might come handy to future viewers. You can create new array from this array with filter then from there you can check if value exist on that array or not. You can follow below code. Sample
$arr = array(
0 =>array(
"id"=> 1,
"name"=> "Bangladesh",
"action"=> "27"
),
1 =>array(
"id"=> 2,
"name"=> "Entertainment",
"action"=> "34"
)
);
$new = array();
foreach($arr as $value){
$new[$value['id']] = $value;
}
if(array_key_exists(1, $new)){
echo $new[1]['id'];
}
else {
echo "aaa";
}
//print_r($new);

Problem with Building Arrays in Different Coding Styles

I'm having a strange problem while building arrays. I start off with an array that looks like this:
Array (
[0] => Array (
[tag_id] => 19
[tag_translation_id] => 12
[fk_language_id] => 1
[fk_tag_id] => 19
[tag_name] => test
)
[1] => Array (
[tag_id] => 20
[tag_translation_id] => 14
[fk_language_id] => 1
[fk_tag_id] => 20
[tag_name] => testa
)
[2] => Array (
[tag_id] => 20
[tag_translation_id] => 15
[fk_language_id] => 3
[fk_tag_id] => 20
[tag_name] => fdfda
)
)
What I want to do is merge each result with the same tag_id into a single array. This works:
$tags = array();
foreach($results->as_array() as $key=>$result)
{
if(!in_array($result['tag_id'], $tags))
{
$tags[$result['tag_id']] = array();
}
}
foreach($results->as_array() as $result)
{
array_push($tags[$result['tag_id']], array($result['fk_language_id'] , $result['tag_name']));
}
Here is the intended result:
Array (
[19] => Array (
[0] => Array (
[0] => 1
[1] => test
)
)
[20] => Array (
[0] => Array (
[0] => 1
[1] => testa
)
[1] => Array (
[0] => 3
[1] => fdfda
)
)
)
However, I've got two loops here, and I know this isn't ideal. Why do THESE not work??
$tags = array();
foreach($results->as_array() as $key=>$result)
{
$tags[$result['tag_id']] .= array($result['fk_language_id'] , $result['tag_name']);
}
With this example I get two empty arrays...
Array ( [19] => Array [20] => ArrayArray )
Or even...
$tags = array();
foreach($results->as_array() as $key=>$result)
{
if(!in_array($result['tag_id'], $tags))
{
$tags[$result['tag_id']] = array();
}
array_push($tags[$result['tag_id']], array($result['fk_language_id'] , $result['tag_name']));
}
Which for some reason overwrites the first value of the second array with the second value of the second array.
Array (
[19] => Array (
[0] => Array (
[0] => 1
[1] => test
)
)
[20] => Array (
[0] => Array (
[0] => 3
[1] => fdfda
)
)
)
What am I doing wrong in the second 2 examples?
To answer your question, your second method fails because you're using the incorrect .= operator. Your third method fails because your !in_array check is always false (it checks whether the value is in the array, not whether the key is set) and overwrites the array each iteration. You only really need this (as mentioned by others, in pseudo-code):
$result = array();
foreach ($array as $values) {
$result[$values['key']][] = array($values['foo'], $values['bar']);
}
The .= operator is string concatenation. Arrays are merged with +=.
If I understand the issue correctly, the code should go like this:
$tags = array();
foreach ($results as $result)
$tags[$result['tag_id']][] = array($result['fk_language_id'], $result['tag_name']);
$tags = array();
foreach($results->as_array() as $key=>$result)
{
$tags[$result['tag_id']] .= array($result['fk_language_id'] , $result['tag_name']);
}
you cannot add a value to an array with the .= (dot equal) operator.
why are you doing $results->as_array() ????
do simply:
foreach($results as $key=>$result) {
Instead of using .= try using []
$tags = array();
foreach ($results as $result)
{
if(!isset($tags[$result['tag_id']]))
$tags[$result['tag_id']] = array();
$tags[$result['tag_id']][] = array($result['fk_language_id'], result['tag_name']);
}
.= is to concatinate a string
+= is to concatinate a number
[] is to concatinate to an array
Hope this helps?
Edit: Noticed that it "might" fail if the tag_id doesn't already exist in the array, so it might be worth just checking first and setting it to an array just in case.

How can I create multidimensional arrays from a string in PHP?

So My problem is:
I want to create nested array from string as reference.
My String is "res[0]['links'][0]"
So I want to create array $res['0']['links']['0']
I tried:
$result = "res[0]['links'][0]";
$$result = array("id"=>'1',"class"=>'3');
$result = "res[0]['links'][1]";
$$result = array("id"=>'3',"class"=>'9');
when print_r($res)
I see:
<b>Notice</b>: Undefined variable: res in <b>/home/fanbase/domains/fanbase.sportbase.pl/public_html/index.php</b> on line <b>45</b>
I need to see:
Array
(
[0] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 1
[class] => 3
)
)
)
[1] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 3
[class] => 9
)
)
)
)
Thanks for any help.
So you have a description of an array structure, and something to fill it with. That's doable with something like:
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
// unoptimized, always uses strings
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
array_create( $res, "[0]['links'][0]", array("id"=>'1',"class"=>'3') );
array_create( $res, "[0]['links'][1]", array("id"=>'3',"class"=>'9') );
Note how the array name itself is not part of the structure descriptor. But you could theoretically keep it. Instead call the array_create() function with a $tmp variable, and afterwards extract() it to achieve the desired effect:
array_create($tmp, "res[0][links][0]", array(1,2,3,4,5));
extract($tmp);
Another lazy solution would be to use str_parse after a loop combining the array description with the data array as URL-encoded string.
I have a very stupid way for this, you can try this :-)
Suppose your string is "res[0]['links'][0]" first append $ in this and then put in eval command and it will really rock you. Follow the following example
$tmp = '$'.'res[0]['links'][0]'.'= array()';
eval($tmp);
Now you can use your array $res
100% work around and :-)
`
$res = array();
$res[0]['links'][0] = array("id"=>'1',"class"=>'3');
$res[0]['links'][0] = array("id"=>'3',"class"=>'9');
print_r($res);
but read the comments first and learn about arrays first.
In addition to mario's answer, I used another function from php.net comments, together, to make input array (output from jquery form serializeArray) like this:
[2] => Array
(
[name] => apple[color]
[value] => red
)
[3] => Array
(
[name] => appleSeeds[27][genome]
[value] => 201
)
[4] => Array
(
[name] => appleSeeds[27][age]
[value] => 2 weeks
)
[5] => Array
(
[name] => apple[age]
[value] => 3 weeks
)
[6] => Array
(
[name] => appleSeeds[29][genome]
[value] => 103
)
[7] => Array
(
[name] => appleSeeds[29][age]
[value] => 2.2 weeks
)
into
Array
(
[apple] => Array
(
[color] => red
[age] => 3 weeks
)
[appleSeeds] => Array
(
[27] => Array
(
[genome] => 201
[age] => 2 weeks
)
[29] => Array
(
[genome] => 103
[age] => 2.2 weeks
)
)
)
This allowed to maintain numeric keys, without incremental appending of array_merge. So, I used sequence like this:
function MergeArrays($Arr1, $Arr2) {
foreach($Arr2 as $key => $Value) {
if(array_key_exists($key, $Arr1) && is_array($Value)) {
$Arr1[$key] = MergeArrays($Arr1[$key], $Arr2[$key]);
}
else { $Arr1[$key] = $Value; }
}
return $Arr1;
}
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
$input = $_POST['formData'];
$result = array();
foreach ($input as $k => $v) {
$sub = array();
array_create($sub, $v['name'], $v['value']);
$result = MergeArrays($result, $sub);
}

Categories