Modifying one dimenstional array into two dimensional array php - php

I have a single-dimensional array $rec = ['123','456','789'] that I would like to modify into an array like:
array(
'id' => 0,
'addr' => 123,
),
array(
'id' => 0,
'addr' => 456,
),
array(
'id' => 0,
'addr' => 789,
),
To achieve that I have tried looping the original array and inserting each row into the new array like:
$rec = ['123','456','789']
$newList = [];
foreach($rec as $i => $r){
$row = array(
'id' => $i,
'addr' => $r,
);
$newList = array_combine($newList,$row);
}
return $newList;
This results in
{
"id": 2,
"addr": "789"
}
How do I go about to get what I want?

You cannot use array_combine for this purpose
$rec = ['123','456','789'];
$newList = [];
foreach($rec as $i => $r){
$newList[] = array(
'id' => 0,
'addr' => $r,
);
}
var_dump($newList) ;
var_dump Result will be
array(3) {
[0]=>
array(2) {
["id"]=>
int(0)
["addr"]=>
string(3) "123"
}
[1]=>
array(2) {
["id"]=>
int(0)
["addr"]=>
string(3) "456"
}
[2]=>
array(2) {
["id"]=>
int(0)
["addr"]=>
string(3) "789"
}
}
echo json_encode($newList) ;
[
{
"id": 0,
"addr": "123"
},
{
"id": 0,
"addr": "456"
},
{
"id": 0,
"addr": "789"
}
]

$rec = ['123','456','789'];
$newArray = [];
foreach($rec as $item) {
$newArray[] = [
'id' => 0, // or whatever number you want here
'addr' => $item,
];
}
var_dump($newArray);
Result:
//array (size=3)
// 0 =>
// array (size=2)
// 'id' => int 0
// 'addr' => string '123' (length=3)
// 1 =>
// array (size=2)
// 'id' => int 0
// 'addr' => string '456' (length=3)
// 2 =>
// array (size=2)
// 'id' => int 0
// 'addr' => string '789' (length=3)
This can also be done using a for loop(or any other sort of loop for that matter).
Using your original idea, we can also achive that:
$rec = ['123','456','789'];
$newList = [];
foreach($rec as $i => $r){
$row = array(
'id' => $i,
'addr' => $r,
);
$newList[] = array_combine(array_keys($row), array_values($row));
}
var_dump($newList);
Result:
array (size=3)
0 =>
array (size=2)
'id' => int 0
'addr' => string '123' (length=3)
1 =>
array (size=2)
'id' => int 1
'addr' => string '456' (length=3)
2 =>
array (size=2)
'id' => int 2
'addr' => string '789' (length=3)
Lets take a look at what array_combine does
/**
* Creates an array by using one array for keys and another for its values
* #link https://php.net/manual/en/function.array-combine.php
* #param array $keys <p>
* Array of keys to be used. Illegal values for key will be
* converted to string.
* </p>
* #param array $values <p>
* Array of values to be used
* </p>
* #return array|false the combined array, false if the number of elements
* for each array isn't equal or if the arrays are empty.
* #meta
*/
#[Pure]
function array_combine(array $keys, array $values) { }
So you would infact need to get array_keys and array_values from the $row array, also add the new array to the original using []. Which is very redundant.

try this
$rec = ['123','456','789'];
array_walk($rec, function($value,&$startNum ) use(&$result){
$result[]=['id'=>$startNum ++,'addr'=>$value];
},);
print_r($result);
Output
Array (
[0] => Array ( [id] => 0 [addr] => 123 )
[1] => Array ( [id] => 1 [addr] => 456 )
[2] => Array ( [id] => 2 [addr] => 789 ) )

Related

Reorganizing a PHP array structure (arrays within arrays)

I have this array within array which contains a lot of values:
183 =>
array (size=3)
0 => string 'DE' (length=2)
1 => string '2015-06-09' (length=10)
2 => string 'GK' (length=2)
184 =>
array (size=3)
0 => string 'DE' (length=2)
1 => string '2015-06-08' (length=10)
2 => string 'GL' (length=2)
185 =>
array (size=3)
0 => string 'FR' (length=2)
1 => string '2015-06-09' (length=10)
2 => string 'GN' (length=2)
186 =>
array (size=3)
0 => string 'FR' (length=2)
1 => string '2015-09-08' (length=10)
2 => string 'GO' (length=2)
0 is the country code. 1 is a date. 2 is a column on an Excel file.
I want to organize it in this way:
2015-06-09 =>
array (size=3)
DE =>
array (size=2)
column => GK
download => 666
FR =>
array (size=2)
column => GN
download => 777
2015-06-08 =>
array (size=3)
DE =>
array (size=2)
column => GL
download => 666
FR =>
array (size=2)
column => GO
download => 777
So the same date can show up more than once. if it gets to an array value with the same date - it inserts in it the country code with and its' column.
if it has more than 1 country - it adds a new country. (with the 'download' and column values).
I have this function:
function get_cols_to_array_by_date($array) {
$mainarr = array();
$last_in_arr = count($array);
for ($i=0; $i<$last_in_arr; $i++){
$mainarr[$array[$i][1]] = array( $array[$i][0]=> array('downloads'=> 666, 'col'=>$array[$i][2]) );
}
return $mainarr;
}
which outputs an array that runs over the country when it gets to the same date and doesn't give me an array of countries.
What part am I missing in my code?
Is there a simpler way to do it? ( PHP syntax shortcuts ;) )
Assuming that the downloads is the key of the initial array, and each element has 3 elements(date and 2 countries):
Code:
//demo array
$old = array(
555=>array(
0 => 'DE',
1 => '2015-06-09',
2 => 'GK'),
234=>array(
0 => 'DE',
1 => '2015-06-08',
2 => 'GL'),
123=>array(
0 => 'FR',
1 => '2015-06-09',
2 => 'GN')
);
$new = array();
foreach($old as $key=>$arrayValues)
{
if(!array_key_exists($arrayValues[1], $new)){ //check if there is already a key by date
$new[$arrayValues[1]] = array();
}
$new[$arrayValues[1]][$arrayValues[0]] = array('column'=>$arrayValues[2], 'downloads'=>$key); //append formated array
}
echo "<pre>";
var_dump($new);
echo "</pre>";
Output:
array(2) {
["2015-06-09"]=>
array(2) {
["DE"]=>
array(2) {
["column"]=>
string(2) "GK"
["downloads"]=>
int(555)
}
["FR"]=>
array(2) {
["column"]=>
string(2) "GN"
["downloads"]=>
int(123)
}
}
["2015-06-08"]=>
array(1) {
["DE"]=>
array(2) {
["column"]=>
string(2) "GL"
["downloads"]=>
int(234)
}
}
}
Try looping and checking if element exists, if not - add it.
$result = [];
foreach ($myArray as $key => $values) {
if (!isset($result[$values[1]])) {
$result[$values[1]] = [
$values[0] => [
'column' => $values[2],
'download' => $key,
]
];
} elseif (!isset($result[$values[1]][$values[0]])) {
$result[$values[1]][$values[0]] = [
'column' => $values[2],
'download' => $key,
];
}
}
Sandbox

PHP How to sum values of the array of the same key

This Question might seem duplicate, but I swear to have tried and tried thousands of solutions for many hours now...
I have got an associative multidimentional array like this:
1 =>
array (size=1)
'Pld' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
2 =>
array (size=1)
'Aln' =>
array (size=2)
'score_good_answers' => string '0' (length=1)
'score_bad_answers' => string '1' (length=1)
3=>
array (size=1)
'IPS' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
4 =>
array (size=1)
'Pld' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
5 =>
array (size=1)
'Aln' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
6 =>
array (size=1)
'Aln' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
FOR Var_Export:
1=> array ( 'Pld' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 2 => array ( 'Aln' => array ( 'score_good_answers' => '0', 'score_bad_answers' => '1', ), ), 3 => array ( 'IPS' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 4 => array ( 'Pld' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 5 => array ( 'Aln' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 6 => array ( 'Aln' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ),
I need to SUM the all the 'score_good_answers' and the 'score_bad_answers' for all Alns and Plds and so forth.
The Worse case scenario is that, this keys i.e: are changeable values.
At this level, whatever solution that works will be well appreciated.
I tried the Accepted Answer in this SO Question: How to sum values of the array of the same key?
However, It seems to throw several Errors....
And I Tried Several More Solutions from several SO Questions,
i.e: How to sum values of the array of the same key?, Array sum of value based on same key, How to sum values via the same key and group by other key and many more...
An other close one was this:How to sum same array in php
And tried:
$array2 = array();
for($f = 0; $f<count($getCategories); $f++){
foreach($getCategories[$i] as $k=>$v) {
if(!isset($array2[$v['Aln']])) {
$array2[$v['Aln']] = $v;
} else {
$array2[$v['Aln']]['score_good_answers'] += $v['score_good_answers'];
}
}
} var_dump($array2);
I still get Several Errors including invalid arguments undefined offsets and many more
Humbly request for any suggestion.
Thank you very much
You can use this code:
$answers = array();
foreach ($getCategories as $categories){
foreach($categories as $category => $scores){
foreach ($scores as $type => $score){
if (isset($answers[$category][$type])){
$answers[$category][$type] += (int) $score;
} else {
$answers[$category][$type] = (int) $score;
}
}
}
}
The output of will be the following array:
Array
(
[Pld] => Array
(
[score_good_answers] => 2
[score_bad_answers] => 0
)
[Aln] => Array
(
[score_good_answers] => 2
[score_bad_answers] => 1
)
[IPS] => Array
(
[score_good_answers] => 1
[score_bad_answers] => 0
)
)
The variable that holds the key is named $f, but you try to use the undefined variable $i on the next line, see? That is one of your warnings and will not do what you want it to. Use $f on the second line.
for($f = 0; $f<count($getCategories); $f++){
foreach($getCategories[$i] as $k=>$v) {
Your data structure seems a bit odd? Is there always just one key in the second top-most array?
This would be prettier if possible:
array(2) {
[0] => stdClass#1 (3) {
public $name => string(4) "Pld"
public $score_good_answers => int(1)
public $score_bad_answers=> int(0)
}
[1] => stdClass#1 (3) {
public $name => string(4) "Aln"
public $score_good_answers => int(0)
public $score_bad_answers=> int(1)
}
}
I can not see what end result you want, but give this a try, might not fit what you want though.
$goodAnswersByCategoryDataKey = array();
$badAnswersByCategoryDataKey = array();
foreach ($categories as $i => $category) {
foreach ($category as $categoryDataKey => $categoryData) {
if (!isset($goodAnswersByCategoryDataKey[$categoryDataKey])) {
$goodAnswersByCategoryDataKey[$categoryDataKey] = 0;
}
$goodAnswersByCategoryDataKey[categoryDataKey] += $categoryData['score_good_answers'];
if (!isset($badAnswersByCategoryDataKey[$categoryDataKey])) {
$badAnswersByCategoryDataKey[$categoryDataKey] = 0;
}
$badAnswersByCategoryDataKey[$categoryDataKey] += $categoryData['score_bad_answers'];
}
}
var_dump(goodAnswersByCategoryDataKey);
var_dump(badAnswersByCategoryDataKey);
If it's an iterative structure like in your example you can do this :
$answers = [];
$nbCat = count($getCategories);
for($i = 0; $i < $nbCat; $i++) {
foreach($getCategories[$i] as $key => $scores) {
if(empty($answers[$key])) {
$answers[$key] = $scores;
}
else {
$answers[$key]['score_good_answers'] += $scores['score_good_answers'];
$answers[$key]['score_bad_answers'] += $scores['score_bad_answers'];
}
}
}

Merge arrays with same values

I have an array on input with ids of graphic elements and I need to find groups of them. I was trying to use array_search and array_marge but without success.
I have array of siblings:
'siblings' =>
array (size=6)
0 =>
array (size=2)
0 => int 0
1 => int 1
1 =>
array (size=2)
0 => int 2
1 => int 3
2 =>
array (size=2)
0 => int 3
1 => int 5
3 =>
array (size=2)
0 => int 4
1 => int 6
4 =>
array (size=2)
0 => int 4
1 => int 7
5 =>
array (size=2)
0 => int 6
1 => int 7
I need output like following:
'groups' =>
array (size=6)
0 =>
array (size=2)
0 => int 0
1 => int 1
1 =>
array (size=2)
0 => int 2
1 => int 3
2 => int 5
2 =>
array (size=2)
0 => int 4
1 => int 6
2 => int 7
I can output this by following:
$groups[] = array_unique(array_merge($siblings[0]));
$groups[] = array_unique(array_merge($siblings[1],$siblings[2]));
$groups[] = array_unique(array_merge($siblings[3],$siblings[4],$siblings[5]));
var_dump($groups); // will output the previous output of groups
But I need function that will work on large scale.
It may not be so efficient but it works. The normal idea is loop through the array, check the intersection of the current with the remaining inner arrays. If there is some intersection, just merge them into the current, otherwise prepare the next arrays set (to loop and extract the next group):
$a = array('siblings' => array(array(0,1),array(2,3),array(3,5),
array(4,6),array(4,7),array(6,7)));
$g[] = $a["siblings"][0];
$round = array_slice($a["siblings"],1);
$temp = array();
$i = 0;
while(count($round) > 0){
$v = array_shift($round);
if(count(array_intersect($g[$i],$v)) > 0)
$g[$i] = array_unique(array_merge($g[$i],$v));
else $temp[] = $v;
if(count($round) == 0 && count($temp) > 0) {
$g[] = $temp[0];
$i++;
$round = array_slice($temp,1);
$temp = array();
}
}
$groups["groups"] = $g;
var_dump($groups);
Result:
array(1) {
["groups"]=> array(3) {
[0]=> array(2) {
[0]=> int(0)
[1]=> int(1) }
[1]=> array(3) {
[0]=> int(2)
[1]=> int(3)
[3]=> int(5) }
[2]=> array(3) {
[0]=> int(4)
[1]=> int(6)
[2]=> int(7) } } }
Perhaps something like this would work. It doesn't compare siblings against each other. Instead it flattens the array, removes duplicates and then breaks it into groups of 3.
<?php
$siblings = array(
array(0, 1),
array(2, 3),
array(3, 5),
array(4, 6),
array(4, 7),
array(6, 7),
);
$merged = array();
$grouped = array();
for ($i = 0; $i < count($siblings); $i++) {
array_push($merged, $siblings[$i][0]);
array_push($merged, $siblings[$i][1]);
}
$merged = array_unique($merged);
$merged = array_chunk($merged, 3);
print_r($merged);
?>
Gives the following output:
Array
(
[0] => Array
(
[0] => 0
[1] => 1
[2] => 2
)
[1] => Array
(
[0] => 3
[1] => 5
[2] => 4
)
[2] => Array
(
[0] => 6
[1] => 7
)
)

Shift an element to the end of array

I have an array which contains list of pagrank values. Consider below array:
Array
(
[0] => stdClass Object
(
[pagerank] => 3
)
[1] => stdClass Object
(
[pagerank] => 1
)
[2] => stdClass Object
(
[pagerank] => R
)
[3] => stdClass Object
(
[pagerank] => 2
)
[4] => stdClass Object
(
[pagerank] => 7
)
)
I want to shift/move page rank with 'R' like:
[2] => stdClass Object
(
[pagerank] => R
)
to the end of array and it should be on last index of array?
Edit: The array key is unknown.
If the index is unknown:
foreach($array as $key => $val) {
if($val->pagerank == 'R') {
$item = $array[$key];
unset($array[$key]);
array_push($array, $item);
break;
}
}
If you don't want to modify the array while it is being iterated over just find the index then make the modifications.
$foundIndex = false;
foreach($array as $key => $val) {
if($val->pagerank == 'R') {
$foundIndex = $key;
break;
}
}
if($foundIndex !== false) {
$item = $array[$foundIndex];
unset($array[$foundIndex]);
array_push($array, $item);
}
$item = $array[2];
unset($array[2]);
array_push($array, $item);
Something like this?
$var = array(
'name' => 'thename',
'title' => 'thetitle',
'media' => 'themedia'
);
// Remove first element (the name)
$name = array_shift($var);
// Add it on to the end
$var['name'] = $name;
var_dump($var);
/*
array(3) {
["title"]=>
string(8) "thetitle"
["media"]=>
string(8) "themedia"
["name"]=>
string(7) "thename"
}
*/
Ref: http://forums.phpfreaks.com/topic/177878-move-array-index-to-end/
$item=null;
foreach ($array['pagerank'] as $key => $value)
{
if( $value=="R")
{
$item = $array[$key];
unset($array[$key]);
break;
}
}
if($item !=null)
array_push($array, $item);
Try this :
$arr = array(array("pagerank" => 3),
array("pagerank" => 1),
array("pagerank" => 'R'),
array("pagerank" => 4),
array("pagerank" => 7),
array("pagerank" => 5),
array("pagerank" => 2)
);
foreach($arr as $key=>$ar){
if($ar["pagerank"] == "R"){
$unset = $key;
break;
}
}
$val = $arr[$unset];
unset($arr[$unset]);
$arr[] = $val;
print_r($arr);
If what you're looking for is specifically the value of r, you can use array_search
array_search returns the key if an item exists in the array, otherwise returns false.
$needle = "R";
if($key = array_search($needle, $pageRankArray)) {
unset($pageRankArray[$key]); // Delete an item from the array
array_push($pageRankArray, $needle); // inserts element at the end of the array
}
If you want to place R as the last value and keeping your keys, you could do this:
$arr = array(
(object)array('pagerank' => 1),
(object)array('pagerank' => 'R'),
(object)array('pagerank' => 2),
);
// Store in temp var.
$tmp_arr = $arr;
// Sort temp array to put 'R' in top.
asort($tmp_arr);
// Reset to be able to find the first key in the sorted array.
reset($tmp_arr);
// Get key from first value in array.
$key = key($tmp_arr);
// Store value from first key.
$item = $tmp_arr[$key];
// Unset key from original array.
unset($arr[$key]);
// Insert as last value in original array using original key.
$arr[$key] = $item;
// Print result.
var_dump($arr);
This will give you:
array(3) {
[0]=>
object(stdClass)#1 (1) {
["pagerank"]=>
int(1)
}
[2]=>
object(stdClass)#3 (1) {
["pagerank"]=>
int(2)
}
[1]=>
object(stdClass)#2 (1) {
["pagerank"]=>
string(1) "R"
}
}
See: http://codepad.org/gPhrktuJ
foreach ($arr as $key => $value){
if ($value->pagerank == 'R'){
$arr[] = $value;
unset($arr[$key]);
break;
}
}
$arr = array_values($arr);
If you have more than one object with a 'R' value:
$current_array = $sorted_array = Array(
...
);
foreach($current_array as $current_key => $element){
if($element->pagerank == 'R'){
unset($sorted_array[$current_key]);
$sorted_array[] = $element;
}
}
unset($current_array);
Just use array_filter.
Taking $arr as input array:
$arr=Array
(
(Object) ['pagerank' => 3],
(Object) ['pagerank' => 1],
(Object) ['pagerank' => "R"],
(Object) ['pagerank' => 2],
(Object) ['pagerank' => 7],
);
$result=array_filter($arr,function($item){return $item->pagerank!="R";})+$arr;
var_dump($arr,$result);
The result will be:
array (size=5)
0 =>
object(stdClass)[1]
public 'pagerank' => int 3
1 =>
object(stdClass)[2]
public 'pagerank' => int 1
2 =>
object(stdClass)[3]
public 'pagerank' => string 'R' (length=1)
3 =>
object(stdClass)[4]
public 'pagerank' => int 2
4 =>
object(stdClass)[5]
public 'pagerank' => int 7
array (size=5)
0 =>
object(stdClass)[1]
public 'pagerank' => int 3
1 =>
object(stdClass)[2]
public 'pagerank' => int 1
3 =>
object(stdClass)[4]
public 'pagerank' => int 2
4 =>
object(stdClass)[5]
public 'pagerank' => int 7
2 =>
object(stdClass)[3]
public 'pagerank' => string 'R' (length=1)

PHP - Unexpected array_merge_recursive() output

I have this code
$a1 = array(
'success' => TRUE,
'data' => array(
'foo' =>
array(
21 =>
array(
1 =>
array(1, 2, 3, 4, 5)
)
)
)
);
$a2 = array(
'success' => TRUE,
'data' => array(
'foo' =>
array(
21 =>
array(
7 =>
array(6, 7, 8, 9, 10)
)
)
)
);
$results = array();
$results = array_merge_recursive($results, $a1['data']);
$results = array_merge_recursive($results, $a2['data']);
var_dump($results);
From what I understood of array_merge_recursive(), I am expecting the results would be
array
'foo' =>
array
21 =>
array
1 =>
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
7 =>
0 => int 6
1 => int 7
2 => int 8
3 => int 9
4 => int 10
Instead I get this
array
'foo' =>
array
21 =>
array
1 =>
array
0 => int 1
1 => int 2
2 => int 3
3 => int 4
4 => int 5
22 =>
array
7 =>
array
0 => int 6
1 => int 7
2 => int 8
3 => int 9
4 => int 10
Where did the 22 index come from? Why is it outputting differently? Did I use the function wrong?
array_merge_recursive merges elements/arrays from the same depth as the first array, but if both arrays the key is a numerical index and they are the same it then appends to it. This is what is happening in your situation. since then your array is appended at 2nd level where index 21 is found by creating index 22. To receive the desired output you have change your index 21 to a string key like "x21"
Notes from php manual
If the input arrays have the same string keys, then the values for
these keys are merged together into an array, and this is done
recursively, so that if one of the values is an array itself, the
function will merge it with a corresponding entry in another array
too. If, however, the arrays have the same numeric key, the later
value will not overwrite the original value, but will be appended.
I just came across the same issue, I wanted to merge the arrays but surprisingly found the keys were changed automatically in the result. The reason was because my "keys" are string of decimal numbers, without any alphabetic characters.
But luckily I noticed that if the keys have alphabetic characters, they could be reserved. So just came up with the following idea, which would append a letter 'S' to each key recursively before the merge, and later remove it in the final result.
Please refer to the enhanced_array_merge_recursive function for details:
<?php
$aa = [
'10' => 'book',
'14' => ['cat'],
];
$ab = [
'12' => 'cd',
'18' => 'cup',
'14' => ['dog'],
];
var_dump(enhanced_array_merge_recursive($aa, $ab));
function revise_keys($source)
{
if (!is_array($source)) {
return $source;
}
$target = [];
foreach ($source as $key => $value) {
$target['S' . $key] = revise_keys($value);
}
return $target;
}
function revert_keys($source)
{
if (!is_array($source)) {
return $source;
}
$target = [];
foreach ($source as $key => $value) {
$target[substr($key, 1 - strlen($key))] = revert_keys($value);
}
return $target;
}
function enhanced_array_merge_recursive(...$candidates)
{
$merged = [];
foreach ($candidates as $candidate) {
if (!is_array($candidate)) {
continue;
}
$merged = array_merge_recursive($merged, revise_keys($candidate));
}
return revert_keys($merged);
}
Output looks like following:
array(4) {
[10] =>
string(4) "book"
[14] =>
array(1) {
[0] =>
array(2) {
[0] =>
string(3) "cat"
[1] =>
string(3) "dog"
}
}
[12] =>
string(2) "cd"
[18] =>
string(3) "cup"
}

Categories