Check for differnent values between new and old arrays PHP - php

I have an array of values that will get updated periodically. When the array is updated, I want to perform an action using the new values in the updated array.
$old_node->field_name[0]['value'] = 'red'
$old_node->field_name[1]['value'] = 'yellow'
$old_node->field_name[2]['value'] = 'blue'
$updated_node->field_name[0]['value'] = 'green',
$updated_node->field_name[1]['value'] = 'red',
$updated_node->field_name[2]['value'] ='purple',
$updated_node->field_name[3]['value'] = 'blue',
So the values of 'green' and 'purple' are the new values in the new array. I need to run each of the values that are ADDED to the new array through a function. Something like:
foreach(of the newly added values that are in the new array){
//do stuff;
}
Some values may be deleted when the array is updated, so the the key=>value pairs could change.
I've tried:
foreach($updated_node->field_name as $new_value){
if(!in_array($new_value['value'], $old_node->field_name) && $new_value['value'] !== NULL){
//Do stuff;
}
}
But that doesn't work. I've also tried picking out new values with array_diff and array_intersect, but that's not working either.

use array_diff()
$old_array = array(
0 => 'red',
1 =>'yellow',
2 => 'blue'
);
$new_array = array(
0 => 'green',
1 => 'red',
2 =>'purple',
4 => 'blue'
);
$diff = array_diff($new_array, $old_array);
print_r($diff);
/*
Array
(
[0] => green
[2] => purple
)
*/
for your new code
$old_node->field_name[0]['value'] = 'red';
$old_node->field_name[1]['value'] = 'yellow';
$old_node->field_name[2]['value'] = 'blue';
$updated_node->field_name[0]['value'] = 'green';
$updated_node->field_name[1]['value'] = 'red';
$updated_node->field_name[2]['value'] = 'purple';
$updated_node->field_name[3]['value'] = 'blue';
$diff = array();
foreach($updated_node->field_name as $num => $field){
$tmpval = false;
foreach($old_node->field_name as $old){
if($field['value'] == $old['value']){
$tmpval = true;
}
}
if(!$tmpval){
$diff[$num] = $field['value'];
}
}
print_r($diff);
/*
Array
(
[0] => green
[2] => purple
)
*/

$old_array = array(
[0] => 'red',
[1] =>'yellow',
[2] => 'blue',
);
$new_array = array(
[0] => 'green',
[1] => 'red',
[2] =>'purple',
[4] => 'blue',
);
$diff = array_diff($new_array, $old_array);
var_dump($diff);
That results in
array(2) {
[0]=>
string(5) "green"
[2]=>
string(6) "purple"
}
which is the correct (expected) result.

Here is a simple function to load up two arrays with the added and removed values:
function loadArrayDifferences($before, $after, &$added, &$removed) {
$added = array_diff($after, $before);
$removed = array_diff($before, $after);
}
and here is a test script:
<?php
$ar1 = array(
'one',
'two',
'three',
'four'
);
$ar2 = array(
'two',
'four',
'six',
'eight',
);
$adds = array();
$rems = array();
loadArrayDifferences($ar1, $ar2, $adds, $rems);
var_dump($adds);
var_dump($rems);
function loadArrayDifferences($before, $after, &$added, &$removed) {
$added = array_diff($after, $before);
$removed = array_diff($before, $after);
}
which outputs:
array(2) {
[2]=>
string(3) "six"
[3]=>
string(5) "eight"
}
array(2) {
[0]=>
string(3) "one"
[2]=>
string(5) "three"
}

Related

How to group an array into subarrays using its keys?

I am looking to group an array into subarrays based on its keys.
Sample Array
Array
(
[0] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 1
[b_name] => B1
[c_id] => 1
[c_name] => C1
)
[1] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 1
[b_name] => B1
[c_id] => 2
[c_name] => C2
)
[2] => Array
(
[a_id] => 1
[a_name] => A1
[b_id] => 2
[b_name] => B2
[c_id] => 3
[c_name] => C3
)
[3] => Array
(
[a_id] => 2
[a_name] => A2
[b_id] => 3
[b_name] => B3
[c_id] => 4
[c_name] => C4
)
)
I need this sample array to be converted into a JSON array of the following format:
Expected Output
[{
"a_id": 1,
"a_name": "A1",
"b_list": [{
"b_id": 1,
"b_name": "B1",
"c_list": [{
"c_id": 1,
"c_name": "C1"
}, {
"c_id": 2,
"c_name": "C2"
}]
}, {
"b_id": 2,
"b_name": "B2",
"c_list": [{
"c_id": 3,
"c_name": "C3"
}]
}]
}, {
"a_id": 2,
"a_name": "A2",
"b_list": [{
"b_id": 3,
"b_name": "B3",
"c_list": [{
"c_id": 4,
"c_name": "C4"
}]
}]
}]
I was able to group by a key using the code below.
$array = array(
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "1","c_name" => "C1"),
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "2","c_name" => "C2"),
array("a_id" => "1","a_name" => "A1","b_id" => "2","b_name" => "B2","c_id" => "3","c_name" => "C3"),
array("a_id" => "2","a_name" => "A2","b_id" => "3","b_name" => "B3","c_id" => "4","c_name" => "C4")
);
$return = array();
foreach($array as $val) {
$return[$val["a_id"]][] = $val;
}
print_r($return);
But my actual scenario involves grouping into sub arrays didn't worked.
Looking forward to see if there is an optimized way or useful function to get into my expected JSON response.
Note: I am looking into a generalized use case here . For example : a_list as countries,b_list as states and c_list as cities.
Man that is very specific use case for arrays. Well here is your solution.
$array = <YOUR SAMPLE ARRAY>
$output = [];
/*
* Nesting array based on a_id, b_id
*/
foreach ($array as $item) {
$aid = $item['a_id'];
$bid = $item['b_id'];
$cid = $item['c_id'];
if(!isset($output[$aid])){
$output[$aid] = [
'a_id' => $item['a_id'],
'a_name' => $item['a_name'],
'b_list' => [
$bid => [
'b_id' => $item['b_id'],
'b_name' => $item['b_name'],
'c_list' => [
$cid = [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
]
]
]
]
];
} else if (!isset($output[$aid]['b_list'][$bid])){
$output[$aid]['b_list'][$bid] = [
'b_id' => $item['b_id'],
'b_name' => $item['b_name'],
'c_list' => [
$cid => [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
]
]
];
} else if(!isset($output[$aid]['b_list'][$bid]['c_list'][$cid])) {
$output[$aid]['b_list'][$bid]['c_list'][$cid] = [
'c_id' => $item['c_id'],
'c_name' => $item['c_name']
];
} else {
// Do/Dont overrider
}
}
/*
* Removing the associativity from the b_list and c_list
*/
function indexed($input){
$output = [];
foreach ($input as $key => $item) {
if(is_array($item)){
if($key == 'b_list' || $key == 'c_list'){
$output[$key] = indexed($item);
} else {
$output[] = indexed($item);
}
} else {
$output[$key] = $item;
}
}
return $output;
}
$indexed = indexed($output);
print_r(json_encode($indexed, 128));
Interesting requirement there.
Here is my generalized solution that is also extendable.
function transform($array, $group=[
['a_id','a_name','b_list'],
['b_id','b_name','c_list'],
['c_id','c_name'],
]){
foreach($array as $a){
$r = &$result;
foreach($group as $g){
$x = &$r[$a[$g[0]]];
$x[$g[0]] = $a[$g[0]];
$x[$g[1]] = $a[$g[1]];
if(isset($g[2])) $r = &$x[$g[2]]; else break;
}
}
return transformResult($result);
}
function transformResult($result){
foreach($result as &$a)
foreach($a as &$b)
if(is_array($b)) $b = transformResult($b);
return array_values($result);
}
To extend this solution, all you have to do is modify the $group parameter,
either directly in the function declaration or by passing an appropriate value as the 2nd parameter.
Usage example:
echo json_encode(transform($array), JSON_PRETTY_PRINT);
This will return the same output assuming the same $array input in your example.
Now here is the code that works best in the given situation. I have created a similar situation and then explained the solution in detail.
Situation
The Order Form is multipage depending on the number of days served based on the package selected. Details of each package are stored in the database with the following fields:
package_id (Unique Field)
package_name (Name of the Package, e.g. Package A)
servings_count (Total Servings in a Day)
days_served (Number of Days Served in a Month)
In order to carry forward the selection of meals for each day and serving of that day to store as an Order in the database, I required a Multidimensional Array of PHP that can be defined/populated dynamically.
Expected output is something like:
Array
(
[Day 1] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
[Day 2] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
This above array has been created 100% dynamically based on the explained structure and number of servings and days. Below is the code with some explanation.
First, we have to declare two PHP Arrays.
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
After doing this, run MySQL query to read packages from the database. Now based on the result, do the following:
$total_meals_array = []; //Primary, Multidimension Array
$meals_selected_array = []; //Meals Details Array to be used as primary array's key value.
if( $num_row_packages >= 1 ) {
while($row_packages = mysqli_fetch_array ($result_packages)) {
$package_id = $row_packages['package_id'];
$package_name = $row_packages['package_name'];
$servings_count = $row_packages['servings_count'];
$days_served = $row_packages['days_served'];
//this for loop is to repeat the code inside `$days_served` number of times. This will be defining our primary and main Multidimensional Array `$total_meals_array`.
for ($y = 1; $y <= $days_served; $y++) {
//once inside the code, now is the time to define/populate our secondary array that will be used as primary array's key value. `$i`, which is the meal count of each day, will be added to the key name to make it easier to read it later. This will be repeated `$meals_count` times.
for ($i = 1; $i <= $meals_count; $i++) {
$meals_selected_array["meal_id_" . $i] = "Unique ID";
$meals_selected_array["meal_code_" . $i] = "Meal Name";
$meals_selected_array["meal_type_" . $i] = "Meal";
}
//once our secondary array, which will be used as the primary array's key value, is ready, we will start defining/populating our Primary Multidimensional Array with Keys Named based on `$days_served`.
$total_meals_array["Day " . $y] = $meals_selected_array;
}
}
}
That's it! Our dynamic Multidimensional Array is ready and can be viewed by simply the below code:
print "<pre>";
print_r($total_meals_array);
print "</pre>";
Thank you everyone, specially #yarwest for being kind enough to answer my question.
Here is the code, you can use it for index from a_ to y_ deep. The innerest element is null, if you don't want it. Terminate the for loop before last element, then process last element seperately. You also can do some improvement on this code. Hope this helps.
<?php
$array = array(
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "1","c_name" => "C1"),
array("a_id" => "1","a_name" => "A1","b_id" => "1","b_name" => "B1","c_id" => "2","c_name" => "C2"),
array("a_id" => "1","a_name" => "A1","b_id" => "2","b_name" => "B2","c_id" => "3","c_name" => "C3"),
array("a_id" => "2","a_name" => "A2","b_id" => "3","b_name" => "B3","c_id" => "4","c_name" => "C4")
);
$arrays = array_map(function($v){return array_chunk($v, 2, true);}, $array);
$result = [];
foreach($arrays as $value)
{
$ref = &$result;
$len = count($value);
$index = 0;
for(; $index < $len; $index++)
{
$arr = $value[$index];
$char = key($arr)[0];
$charAdd = chr(ord($char)+1);
$key = $arr[$char.'_id'].$arr[$char.'_name'];
$listKey = $charAdd.'_list';
foreach($arr as $k => $v)
{
$ref[$key][$k] = $v;
}
$ref = &$ref[$key][$listKey];
}
}
var_dump($result);
Output: the online live demo
ei#localhost:~$ php test.php
array(2) {
["1A1"]=>
array(3) {
["a_id"]=>
string(1) "1"
["a_name"]=>
string(2) "A1"
["b_list"]=>
array(2) {
["1B1"]=>
array(3) {
["b_id"]=>
string(1) "1"
["b_name"]=>
string(2) "B1"
["c_list"]=>
array(2) {
["1C1"]=>
array(3) {
["c_id"]=>
string(1) "1"
["c_name"]=>
string(2) "C1"
["d_list"]=>
NULL
}
["2C2"]=>
array(3) {
["c_id"]=>
string(1) "2"
["c_name"]=>
string(2) "C2"
["d_list"]=>
NULL
}
}
}
["2B2"]=>
array(3) {
["b_id"]=>
string(1) "2"
["b_name"]=>
string(2) "B2"
["c_list"]=>
array(1) {
["3C3"]=>
array(3) {
["c_id"]=>
string(1) "3"
["c_name"]=>
string(2) "C3"
["d_list"]=>
NULL
}
}
}
}
}
["2A2"]=>
array(3) {
["a_id"]=>
string(1) "2"
["a_name"]=>
string(2) "A2"
["b_list"]=>
array(1) {
["3B3"]=>
array(3) {
["b_id"]=>
string(1) "3"
["b_name"]=>
string(2) "B3"
["c_list"]=>
array(1) {
["4C4"]=>
array(3) {
["c_id"]=>
string(1) "4"
["c_name"]=>
string(2) "C4"
["d_list"]=>
&NULL
}
}
}
}
}
}
This is rather interesting. As far as I can tell, you are trying to transform a flat array into a multidimensional array, as well as transforming the keys into a multidimensional representation.
The top level difference seems to reside in the part before the underscore of the a_* keys.
Then, for each of these keys, every other *_ letters should induce it's own list.
This recursive function does the trick without hardcoding, will work with whatever number of levels, letters (or whatever else) and right identifiers.
It seems to return exactly the json you show in the sample ($array being the array as defined in your question)
$multidimension = multidimensionalify($array, ['a', 'b', 'c'], ['name']);
var_dump(json_encode($multidimension, JSON_PRETTY_PRINT));
function multidimensionalify(
array $input,
array $topLevelLetters,
array $rightHandIdentifiers,
$level = 0,
$parentId = null,
$uniqueString = 'id'
)
{
$thisDimension = [];
$thisLetter = $topLevelLetters[$level];
foreach ($input as $entry)
{
$thisId = $entry["{$thisLetter}_{$uniqueString}"];
$condition = true;
if ($parentId !== null)
{
$parentLetter = $topLevelLetters[$level - 1];
$condition = $entry["{$parentLetter}_{$uniqueString}"] === $parentId;
}
if (!isset($thisDimension[$thisId]) && $condition)
{
$thisObject = new stdClass;
$thisObject->{"{$thisLetter}_{$uniqueString}"} = $thisId;
foreach ($rightHandIdentifiers as $identifier)
{
$thisObject->{"{$thisLetter}_{$identifier}"} = $entry["{$thisLetter}_{$identifier}"];
}
if (isset($topLevelLetters[$level + 1])) {
$nextLetter = $topLevelLetters[$level + 1];
$thisObject->{"{$nextLetter}_list"} = multidimensionalify($input, $topLevelLetters, $rightHandIdentifiers, $level + 1, $thisId, $uniqueString);
}
$thisDimension[$thisId] = $thisObject;
}
}
return array_values($thisDimension);
}
Try this function just pass your array and key name for grouping and then convert to json.
public function _group_by($array, $key) {
$return = array();
foreach ($array as $val) {
$return[$val[$key]][] = $val;
}
return $return;
}

PHP - Recursively set each array element's key to the value of a child element when given the childs key name

I'll start by showing a non-recursive example
Non- recursive example
$given_key_name = 'site_id';
$rows[] = array(
'site_id' => '0',
'language_id' => '1',
'name' => 'sitename',
'description' =>'site desc',
);
$results = array();
foreach($rows as $row){
$key_value = $row[$given_key_name];
unset($row[$given_key_name]);
$results[$key_value] = $row;
}
// OR This method is faster than the forloop
$results = array_combine(array_column($rows, $given_key_name),$rows);
foreach($results as &$row){
unset($row[$given_key_name]);
}
$results Equals
$results[0] = array(
'language_id' => '1',
'name' => 'sitename',
'description' =>'site desc',
);
Simple, the key name has been set to the value of the given child element. But I would like to be able to nest and unnest by using multiple key names.
Example
$given_key_names = array('site_id', 'language_id');
In this case the required result would be.
$results[0][1] = array(
'name' => 'sitename',
'description' =>'site desc',
);
Explanation
The first keys value has been used as the first key in the $results array and a new empty array is created as its value. $results[0] = array();
As there is a second key, its value is set as a key to the newly created array and its value is also a new empty array. $results[0][1] = array();
As there are no more keys the empty array is populated with the remaining values
$results[0][1] = array(
'name' => 'sitename',
'description' =>'site desc',
);
so i would like two functions nestByKeyNames and unNestByKeyName.
NestByKeyNames Function
Christians Answer solves this
function nestByKeyNames($arrayRows, $arrayKeyOrder){
// Prepare resulting array
$arrayResult = array();
// Cycle the input array
foreach($arrayRows as $someRow){
// We will acomplish this using references
$current = &$arrayResult;
// get the current level
foreach($arrayKeyOrder as $someKey){
$someValue = $someRow[$someKey];
if(isset($current[$someValue])){
$current = &$current[$someValue];
}else{
$current[$someValue] = array();
$current = &$current[$someValue];
}
unset($someRow[$someKey]);
}
$current = $someRow;
}
return $arrayResult;
}
I wonder whether array_combine(array_column($arrayRows, $key_name),$arrayRows); could be used instead of the first iteration to improve performance?
This represents the results from a mysql select statement.
$rows = array(
array(
'pri_id_1' =>1,
'pri_id_2' =>1,
'pri_id_3' =>1,
'col_1' =>'col_value_1111',
'col_2' =>'col_value_1112',
'col_3' =>'col_value_1113',
),
array(
'pri_id_1' =>1,
'pri_id_2' =>2,
'pri_id_3' =>1,
'col_1' =>'col_value_1211',
'col_2' =>'col_value_1212',
'col_3' =>'col_value_1213',
),
array(
'pri_id_1' =>1,
'pri_id_2' =>3,
'pri_id_3' =>1,
'col_1' =>'col_value_1311',
'col_2' =>'col_value_1312',
'col_3' =>'col_value_1313',
)
);
$keyNames = array('pri_id_1','pri_id_2','pri_id_3');
$results = nestByKeyNames($rows, $keyNames);
The following output is produced
Array
(
[1] => Array
(
[1] => Array
(
[1] => Array
(
[col_1] => col_value_1111
[col_2] => col_value_1112
[col_3] => col_value_1113
)
)
[2] => Array
(
[1] => Array
(
[col_1] => col_value_1211
[col_2] => col_value_1212
[col_3] => col_value_1213
)
)
[3] => Array
(
[1] => Array
(
[col_1] => col_value_1311
[col_2] => col_value_1312
[col_3] => col_value_1313
)
)
)
)
UnNestByKeyNames Function
unNestByKeyNames should be able to take this output and convert it back to the original array providing that it is given the key names.
Christians Answer did not solves this as it doesnt work with a single key name but i can tell its very close.
function unNestByKeyNames($arrayRows, $arrayKeyOrder){
}
$keyNames = array('pri_id_1','pri_id_2','pri_id_3');
$rows = unNestKeyNames($results, $keyNames);
My true goal is to take the results from MYSQL SELECT statement and populate a form using the same naming convention by using nestByKeyNames.
e.g.
<input name="rows[1][1][1][col_1]" value="col_value_1" />
and then convert the $_POST request back into an MYSQL INSERT statement by first using unNestByKeyNames.
From this i will create an INSERT statement.
function returnValues($rows, $column_names){
//validation has been removed for clarity
$implode_VALUES = array();
foreach ($rows as $key => $row) {
$implode_row_values = array();
foreach ($column_names as $column_name) {
$implode_row_values[$column_name] = $row[$column_name];
}
if($implode_row_values){
$implode_VALUES[] = " ('" . implode("','", $implode_row_values) . "') ";
}
}
return $implode_VALUES;
}
$implode_COLUMNS = array('pri_id_1','pri_id_2','pri_id_3','col_1','col_2','col_3');
$implode_VALUES = returnValues($rows, $implode_COLUMNS)
$sql = "INSERT INTO table_name (" . implode(',', $implode_COLUMNS) . ") VALUES " . implode(',', $implode_VALUES);
The final result should produce a sql statement like so
INSERT INTO table_name (pri_id_1,pri_id_2,pri_id_3,col_1,col_2,col_3) VALUES ('1','1','1','NEW_value_1111','NEW_value_1112','NEW_value_1113') , ('1','2','1','NEW_value_1211','NEW_value_1212','NEW_value_1213') , ('1','3','1','NEW_value_1311','NEW_value_1312','NEW_value_1313')
What I Would like
Improvement suggestions on the 'nestByKeyNames' function (performance/ does it have bugs)
help producing 'unNestByKeyNames' code
Improvement suggestions on my '$rows to mysql INSERT' approach
examples of how i could make any of my code perform better.
This was trickier than I first imagined but I believe I have a messy solution.
First of all, this is the data I am working with. dumpr is a custom function that formats var_dump better.
$arrayKeyOrder = array(
'site_id',
'language_id'
);
$original = array(
array(
'site_id' => '0',
'language_id' => '1',
'name' => 'sitename',
'description' =>'site desc',
),
array(
'site_id' => '0',
'language_id' => '2',
'name' => 'sitename',
'description' =>'site desc',
),
array(
'site_id' => '1',
'language_id' => '1',
'name' => 'sitename',
'description' =>'site desc',
),
array(
'site_id' => '2',
'language_id' => '1',
'name' => 'sitename',
'description' =>'site desc',
),
);
$zipped = doZip($original, $arrayKeyOrder);
$unzipped = unZip($zipped, $arrayKeyOrder);
dumpr($original);
dumpr($zipped);
dumpr($unzipped);
Here is the zip and unzip functions:
function doZip($arrayRows, $arrayKeyOrder){
// Prepare resulting array
$arrayResult = array();
// Cycle the input array
foreach($arrayRows as $someRow){
// We will acomplish this using references
$current = &$arrayResult;
// get the current level
foreach($arrayKeyOrder as $someKey){
$someValue = $someRow[$someKey];
if(isset($current[$someValue])){
$current = &$current[$someValue];
}else{
$current[$someValue] = array();
$current = &$current[$someValue];
}
unset($someRow[$someKey]);
}
$current = $someRow;
}
return $arrayResult;
}
function unZip($arrayRows, $arrayKeyOrder, $arrayValues = array(), $depth = 0){
$arrayResults = array();
if($depth < count($arrayKeyOrder)){
foreach($arrayRows as $key => $value){
$arrayValues[$depth] = $key;
$arrayResults[] = unZip($value, $arrayKeyOrder, $arrayValues, $depth + 1);
}
}else{
$extra = array_combine($arrayKeyOrder, $arrayValues);
$result = array_merge($extra, $arrayRows);
return $result;
}
if($depth == 0){
for($i = 1; $i < count($arrayKeyOrder); $i++){
$arrayResults = call_user_func_array('array_merge', $arrayResults);
}
}
return $arrayResults;
}
And finally, here is the output. let me know if this is what you were asking for and if it worked OK on a larger data-set.
/vhost/virtual/sandbox/public/index.php:54
array(4) {
[0] = array(4) {
[site_id] = string(1) "0"
[language_id] = string(1) "1"
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[1] = array(4) {
[site_id] = string(1) "0"
[language_id] = string(1) "2"
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[2] = array(4) {
[site_id] = string(1) "1"
[language_id] = string(1) "1"
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[3] = array(4) {
[site_id] = string(1) "2"
[language_id] = string(1) "1"
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
}
/vhost/virtual/sandbox/public/index.php:55
array(3) {
[0] = array(2) {
[1] = array(2) {
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[2] = array(2) {
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
}
[1] = array(1) {
[1] = array(2) {
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
}
[2] = array(1) {
[1] = array(2) {
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
}
}
/vhost/virtual/sandbox/public/index.php:56
array(4) {
[0] = array(4) {
[site_id] = int(1) 0
[language_id] = int(1) 1
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[1] = array(4) {
[site_id] = int(1) 0
[language_id] = int(1) 2
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[2] = array(4) {
[site_id] = int(1) 1
[language_id] = int(1) 1
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
[3] = array(4) {
[site_id] = int(1) 2
[language_id] = int(1) 1
[name] = string(8) "sitename"
[description] = string(9) "site desc"
}
}
Try this:
// initialize your array
$all_rows = array();
// loop through query results
while( $row = $qry->fetch_assoc() )
{
// temporarily store these vars for easy use later
$s_id = $row['site_id'];
$l_id = $row['language_id'];
// create an empty array based on site_id and language_id
$all_rows[ $s_id ][ $l_id ] = array();
// loop through all columns returned from query
foreach ( $row as $key => $val )
{
// if it's not one of the two primary keys, push it to the array
if ( ! in_array($key, $all_primary_keys) )
{
$all_rows[ $s_id ][ $l_id ][ $key ] = $val;
}
}
}
Is there a reason the below wouldn't work?
$results = array();
while($row = $qry->fetch_assoc()){
$results[$row['site_id']][$row['language_id']] = array(
'name' => $row['name'],
'description' => $row['description']
);
}
Here are two simple functions to solve your problem. I don't put any example as I have used your data and the same function name and arguments.
The first one takes profit of pointers to solve the first step of the problem:
function nestByKeyNames($rows, $aKeys) {
$tab=Array();
foreach ($rows as &$v) {
// calculate the pointer position
$t=&$tab;
foreach ($aKeys as $v1) {
$t=&$t[$v[$v1]];
unset($v[$v1]);
}
// save the value
$t=$v;
}
return $tab;
}
This one uses a recursive algorithm and give the reverse output
function unNestByKeyNames($arrayRows, $aKeys){
$t=Array();
if (!count($aKeys)) return Array($arrayRows);
foreach ($arrayRows as $k=>&$v) {
$res=unNestByKeyNames($v, array_slice($aKeys,1));
foreach ($res as $k1=>$v1) $t[]=array_merge(Array($aKeys[0]=>$k), $v1);
}
return $t;
}
I have no suggestion about your SQL INSERT approach as long as you take care of sql injection, which I suppose might be the reason of your comment "validation has been removed for clarity"
There is no real method to what you wanting if you want to use the primary key you have to know the column name of the primary key hell you should not the columns your querying for. the best way to do it would be to use the AS keyword in the MySQL Query
SELECT primary as ID, ... where primary is the column name of your primary key and now ID is your primary key in the result set.
You can then just do the standard
$sortedResults = array();
while($row = $queryResult->fetch_assoc()){
$rowId = $row["ID"];
$sortedResults[$rowId] = $row;
}
If you don't know what the primary key is there i no reasonable way to obtain it there is a method to get the table columns and then you could go though them find the primary key save it then you have the primary key to do your while on but this would be one hell of an overhead on every query you make.

how to do the calculation in an array

I have an array :
Array
(
[0] => Array
(
[batch_id] => 1
[seq_id] => 1
[q_id] => 2046
[a1] => 0
[a2] => 1
[a3] => 2
[a4] => 3
[a5] => 4
)
)
I need to minus the value of a1-a5 by 1
desire result(e.g. a1):
array(4) {
["w_id"]=>
string(5) "99911"
["q_id"]=>
string(4) "2046"
["c_id"]=>
string(6) "a1"
["rank"]=>
int(1) "-1"
}
My code is as follow:
$result = mysql_query("Select * from table_1");
while($cr = mysql_fetch_array($result)){
$rr_id = $cr['batch_id'].$cr['seq_id'];
$rid = '999'.$rr_id;
$q_id = $cr['q_id'];
foreach ($cr as $k => $v){
if(preg_match('{^a\d+$}',$k)){
$new_insert[] = array(
'w_id'=>$rid,
'q_id' =>$q_id,
'c_id' =>$k,
'rank'=>$v-1
);
}
}
However, the result of rank becomes
array(4) {
["w_id"]=>
string(5) "99911"
["q_id"]=>
string(4) "2046"
["c_id"]=>
string(6) "a1"
["rank"]=>
int(0)
}
Cannot show the value of rank
Any problem with my code??Can someone answer my question thank you very much
You can use :
$data = array_map(function ($v) {
foreach($v as $k => &$x) {
if (preg_match('{^a\d+$}', $k)) {
$x = $x - 1;
}
}
return $v;
}, $data);
print_r($data);
Live Demo
preg_match('{^Item \d+$}',$k)
You've got wrong pattern inside preg_match (keys you are looking for are 'a1','a2'... not 'item 1', 'item 2'...), just use this one:
preg_match('{^a\d+$}',$k)
Just use loop and pre decrementation
foreach($cr as $k=>&$v)
{
--$v['a1'];--$v['a2'];--$v['a3'];--$v['a4'];--$v['a5'];
}
print_r($cr);
I use $cr as your array.
$cr[] = array("batch_id"=>1, "seq_id"=>1, "q_id"=>'2046', "a1"=>1,"a2"=>1,"a3"=>1,"a4"=>1,"a5"=>1);
foreach($cr as $k=>&$v){
$v['a1'] = $v['a1'] - 1;
$v['a2'] = $v['a2'] - 1;
$v['a3'] = $v['a3'] - 1;
$v['a4'] = $v['a4'] - 1;
$v['a5'] = $v['a5'] - 1;
}
print_r($cr);

Global array in php issues

I've found some very helpful answers but still have some problems.
I want to put different rows in global array, WITHOUT removing the other rows.
<?php
global $global_arr;
function first() {
///some code
global $global_arr;
$global_arr[] = array('first' =>
array('1' , '1', '1'));
}
function second() {
///some code
global $global_arr;
$global_arr[] = array('second' =>
array('2' , '2', '2'));
}
function third() {
///some code
global $global_arr;
$global_arr[] = array('third' =>
array('3' , '3', '3'));
}
first();
second();
third();
print_r($global_arr);
I want every of the functions to index the array and add rows respectevly
Thank you in advance!
Edit :
Thank to your help here is the working version :
function first($arr) {
$arr[] = array('first' =>
array(1, 1, 1));
return $arr;
}
function second($arr) {
$arr[] = array('second' =>
array(2, 2, 2));
return $arr;
}
$arr = array();
$arr = first($arr);
$arr = second($arr);
print_r($arr);
Output :
Array ( [0] => Array ( [first] => Array ( [0] => 1 [1] => 1 [2] => 1 ) ) [1] => Array ( [second] => Array ( [0] => 2 [1] => 2 [2] => 2 ) ) )
Any ideas how to be only :
Array ( [first] => Array ( [0] => 1 [1] => 1 [2] => 1) , [second] => Array([0] => 2, [1] => 2, [2] => 2))
?
$global_arr['third'][] = array('3.1' , '3.2', '3.3');
I don't get it - it's the same in/for all three functions.
BTW, I would use only one function like:
<?php
// $arg1 = "one", "two" or "three"
// $arg2 = ARRAY("data1.1", "data1.2", "data1.3") {
function myfunc($arg1, $arg2) {
if (!isset($my_arr)) { static $my_arr = ARRAY(); }
$my_arr[$arg1][] = $arg2;
return $my_arr; // Or code a getter and setter function
}
// Call, as often as you want - like:
myfunc('one', ARRAY('1.1', '1.2','1.3'));
myfunc('two', ARRAY('2.1', '2.2','2.3'));
$arr = myfunc('one', ARRAY('1.4', '1.5','1.6'));
print '<pre>';
var_dump($arr);
print '</pre>';
/* result:
array(2) {
["one"]=>
array(2) {
[0]=>
array(3) {
[0]=>
string(3) "1.1"
[1]=>
string(3) "1.2"
[2]=>
string(3) "1.3"
}
[1]=>
array(3) {
[0]=>
string(3) "1.4"
[1]=>
string(3) "1.5"
[2]=>
string(3) "1.6"
}
}
["two"]=>
array(1) {
[0]=>
array(3) {
[0]=>
string(3) "2.1"
[1]=>
string(3) "2.2"
[2]=>
string(3) "2.3"
}
}
}
*/
?>
Why you want to use global variable? You can simply write
function first($arr) {
$arr[] = array('first' =>
array('3' , '3', '3'));
return $arr;
}
function second($arr) {
$arr[] = array('second' =>
array('3' , '3', '3'));
return $arr;
}
function third($arr) {
$arr[] = array('third' =>
array('3' , '3', '3'));
return $arr;
}
$arr = array();
$arr = first($arr);
$arr = second($arr);
$arr = third($arr);

Merging arrays PHP

I have two arrays of data:
array(2) {
["12:15"]=>
string(84) "http://form.horseracing.betfair.com/horse-racing/010108/Catterick_Bridge-GB-Cat/1215"
["12:20"]=>
string(77) "http://form.horseracing.betfair.com/horse-racing/010108/Southwell-GB-Sou/1220"
}
and
array(2) {
["12:15"]=>
string(90) "http://www.racingpost.com/horses/result_home.sd?race_id=446323&r_date=2008-01-01&popup=yes"
["12:20"]=>
string(90) "http://www.racingpost.com/horses/result_home.sd?race_id=446250&r_date=2008-01-01&popup=yes"
}
I want to merge these based on time, so I end up with an array of values where times in both arrays match only.
array(2) {
["12:15"]=>
array(2) {
[0]=>
string(84) "http://form.horseracing.betfair.com/horse-racing/010108/Catterick_Bridge-GB-Cat/1215"
[1]=>
string(90) "http://www.racingpost.com/horses/result_home.sd?race_id=446323&r_date=2008-01-01&popup=yes"
}
["12:20"]=>
array(2) {
[0]=>
string(77) "http://form.horseracing.betfair.com/horse-racing/010108/Southwell-GB-Sou/1220"
[1]=>
string(90) "http://www.racingpost.com/horses/result_home.sd?race_id=446250&r_date=2008-01-01&popup=yes"
}
}
Wouldn't the following do trick?
$arr1 = array('time' => '14:00', 'rp' => 'blah');
$arr2 = array('time' => '14:00', 'bf' => 'yadda');
if ($arr1['time'] === $arr2['time']) {
$mergedArray = array_merge($arr1, $arr2);
}
$result = array();
foreach ($all_arrays as $a) {
if (!isset($result[$a["time"]])) {
$result[$a["time"]] = array();
}
$result[$a["time"]] = array_merge($result[$a["time"]], $a);
}
$result = array_values($result);
I'm assuming you have any number of these time arrays. It's probably a good idea to store the array like this:
$times = array(
'14:00' => array(...),
'15:00' => array(...),
etc...
);
$temp = array();
foreach($time_arrays as $time_array) {
if(isset($temp[$time_array['time'])) {
$temp[$time_array['time'] = array_merge(temp[$time_array['time'], $time_array);
}
else {
$temp[$time_array['time'] = $time_array;
}
}
$arr1 = array('time' => '14:00', 'rp' => 'blah');
$arr2 = array('time' => '14:00', 'bf' => 'yadda');
$arr3 = $arr1 + $arr2 ;
var_dump( $arr3 ) ;
Gives
array
'time' => string '14:00' (length=5)
'rp' => string 'blah' (length=4)
'bf' => string 'yadda' (length=5)
Using a combination of the answers on offer and some extra Google foo, solved it using the following:
$c = array_merge_recursive($a, $b);

Categories