Merge arrays (PHP) - php

How combine arrays in this way?
source:
Array
(
[0] => Array
(
[id] => 3
[title] => book
[tval] => 10000
)
[1] => Array
(
[id] => 3
[title] => book
[tval] => 1700
)
[3] => Array
(
[id] => 27
[title] => fruit
[tval] => 3000
)
.......
)
result:
Array
(
[0] => Array
(
[id] => 3
[title] => book
[tval] => 10000,1700
)
[1] => Array
(
[id] => 27
[title] => fruit
[tval] => 3000
)
.......
)
please help to solve this problem,
thanks!!!
sorry for bad english(

This should work:
$result = array();
foreach($array as $elem) {
$key = $elem['id'];
if (isset($result[$key])) {
$result[$key]['tval'] .= ',' . $elem['tval'];
} else {
$result[$key] = $elem;
}
}
This basically groups elements by id, concatenating tvals (separated by ,).

Simply building slightly on user576875's method:
$a = array ( 0 => array ( 'id' => 3,
'title' => 'book',
'tval' => 10000
),
1 => array ( 'id' => 3,
'title' => 'book',
'tval' => 1700
),
3 => array ( 'id' => 27,
'bcalias' => 'fruit',
'tval' => 3000
)
);
$result = array();
foreach ($a as $elem) {
$key = $elem['id'];
if (isset($result[$key])) {
$result[$key]['tval'] .= ',' . $elem['tval'];
} else {
$result[$key] = $elem;
}
}
$result = array_merge($result);
var_dump($result);
gives a result of:
array
0 =>
array
'id' => int 3
'title' => string 'book' (length=4)
'tval' => string '10000,1700' (length=10)
1 =>
array
'id' => int 27
'bcalias' => string 'fruit' (length=5)
'tval' => int 3000
The only real difference is the array_merge() to reset the keys

Related

Re-nest arrays into tree using its field as parameter

I'm losing my hair on this one... I have an array structure that print_r's like this (I've hidden unnecessary fields):
[0] => Array
(
[id] => 14
[name] => Foo Directory
)
[1] => Array
(
[id] => 16
[name] => Bar Project
[parent] => Array
(
[id] => 14
[name] => Foo Directory
)
)
[2] => Array
(
[id] => 20
[name] => Baz Project
[parent] => Array
(
[id] => 16
[name] => Bar Project
)
)
[3] => Array
(
[id] => 10
[name] => Qux Project
[parent] => Array
(
[id] => 16
[name] => Bar Project
)
And I need it to be nested like this:
[0] => Array
(
[id] => 14
[name] => Foo Directory
[children] => Array
(
[id] => 16
[name] => Bar Project
[children] => Array
(
[id] => 20
[name] => Baz Project
)
(
[id] => 10
[name] => Qux Project
)
)
)
What I've tried so far
$projTree = array();
foreach ($projects as $project) {
if (isset($project['parent']))
array_push($projTree['children'], $project);
$projTree['id'] = $project['parent']['id'];
}
But that overwrites the previous inserted element. I also tried to walk it recursively, but couldn't figure out the correct callback for that, since it only operates on the leafs of the tree and I need to fully walk it.
How can I do this? Thanks!
Please try like below:-
<?php
$array = Array(
'0' => Array
(
'id' => 14,
'name' => 'Foo Directory'
),
'1' => Array
(
'id' => 16,
'name' => 'Bar Project',
'parent' => Array
(
'id' => 14,
'name' => 'Foo Directory'
)
),
'2' => Array
(
'id' => 20,
'name' => 'Baz Project',
'parent' => Array
(
'id' => 16,
'name' => 'Bar Project'
)
),
'3' => Array
(
'id' => 10,
'name' => 'Qux Project',
'parent' => Array
(
'id' => 16,
'name' => 'Bar Project'
)
)
);
$new_array = array();
$i = 0;
$j = 0;
foreach ($array as $key=>$val){
if(array_key_exists('parent',$val)){
foreach($new_array as $key1=>$val1){
if($val['parent']['name'] === $val1['name']){
$new_array[$key1]['children'][$i]['id'] = $val['id'];
$new_array[$key1]['children'][$i]['name'] = $val['name'];
}else{
foreach ($val1['children'] as $key3=>$val3){
if($val['parent']['name'] === $val3['name']){
$new_array[$key1]['children'][$key3]['children'][$j]['id'] = $val['id'];
$new_array[$key1]['children'][$key3]['children'][$j]['name'] = $val['name'];
}
$j++;
}
$i++;
}
}
}else{
$new_array[$key] = $val;
}
}
echo "<pre/>";print_r($new_array);
Output:- https://eval.in/419591

How to convert a recursive multidimensional array to a straight multidimensional array in PHP?

I have search for a solution for this but couldn't find anything giving me a "straight" multidimensional array back. Flatten is probably not the solution as long as i want to preserve the original sub structure?
In additional i want to summarize qty when the key is repeating.
This is my original array:
Array
(
[60002] => Array
(
[50001] => Array
(
[50002] => Array
(
[10001] => Array
(
[flag] => B
[qty] => 1
)
[10002] => Array
(
[flag] => B
[qty] => 1
)
[10003] => Array
(
[flag] => B
[qty] => 2
)
[flag] => M
[qty] => 1
)
[flag] => M
[qty] => 1
)
[flag] => G
[qty] => 1
)
[10001] => Array
(
[flag] => B
[qty] => 1
)
)
What i basically want is to create a new array looking like this:
Array
(
[10001] => Array
(
[flag] => B
[qty] => 2
)
[10002] => Array
(
[flag] => B
[qty] => 1
)
[10003] => Array
(
[flag] => B
[qty] => 2
)
[50001] => Array
(
[flag] => M
[qty] => 1
)
[50002] => Array
(
[flag] => M
[qty] => 1
)
[60002] => Array
(
[flag] => G
[qty] => 1
)
)
This is tested.
The key is intval().
$value['qty'] += intval($newArray[$key]['qty']);
If the [$key]['qty'] does not exist the intval() will return a zero. This is much faster than using an if else to check if a [$key]['qty'] already exists.
The only possible problem I could anticipate is if the Flag value is different when the key value is the same:
[10001] => Array(
[flag] => M
[qty] => 1
),
[10001] => Array(
[flag] => B
[qty] => 1
)
When this is an issue I resolve the priority with a logic table in an array.
$priority['M']['B'] = 'M'
$priority['B']['M'] = 'M'
$priority['']['M'] = 'M'
$priority['M'][''] = 'M'
$priority['B'][''] = 'B'
$priority['B'][''] = 'B'
settype($newArray[$key]['flag'],'string');
[$newArray[$key]['flag'] = $priority[$value['flag']][$newArray[$key]['flag']]
Data:
$array = array('60002' => Array('50001' => Array('50002' => Array('10001' => Array('flag' => 'B','qty' => 1),'10002' => Array('flag' => 'B','qty' => 1),'10003' => Array('flag' => 'B','qty' => 2),'flag' => 'M','qty' => 1),'flag' => 'M','qty' => 1),'flag' => 'G','qty' => 1),'10001' => Array('flag' => 'B','qty' => 1));
PHP
$newArray = array();
getValues($data);
function getValues($array){
global $newArray;
foreach ($array as $key => $value){
if(is_numeric($value['qty'])) {
$value['qty'] += intval($newArray[$key]['qty']);
$newArray[$key] = array('flag'=>$value['flag'],'qty'=>$value['qty']);
}
if (gettype($value) != 'array'){return;}
getValues($value);
}
}
ksort($newArray);
var_export($newArray);
Result:
array (
10001 =>
array (
'flag' => 'B',
'qty' => 2,
),
10002 =>
array (
'flag' => 'B',
'qty' => 1,
),
10003 =>
array (
'flag' => 'B',
'qty' => 2,
),
50001 =>
array (
'flag' => 'M',
'qty' => 1,
),
50002 =>
array (
'flag' => 'M',
'qty' => 1,
),
60002 =>
array (
'flag' => 'G',
'qty' => 1,
),
)
This seemed to work:
function extractArray(array $source, array &$destination, $originalIndex)
{
foreach($source as $index => $value)
{
if(is_array($value))
extractArray($value, $destination, $index);
else
$destination[$originalIndex][$index] = $value;
}
}
$test = array(
60002 => array
(
50001 => array
(
50002 => array
(
10001 => array
(
'flag' => 'B',
'qty' => 1
),
10002 => array
(
'flag' => 'B',
'qty' => 1
),
10003 => array
(
'flag' => 'B',
'qty' => 2
),
'flag' => 'M',
'qty' => 1
),
'flag' => 'M',
'qty' => 1
),
'flag' => 'G',
'qty' => 1
),
10001 => array
(
'flag' => 'B',
'qty' => 1
)
);
$new = array();
foreach($test as $index => $value)
extractArray($value, $new, $index);
var_dump($new);
die();
You can use a recursive approach to iterate over all levels of the array. For each item you check that it is an array and if it has any of the keys you want checked, add the array consisting of the found attributes.
function flattenArray($array, $keysToCheck) {
$result = array();
foreach($array as $item) {
// check if the current array item is a candidate to
// be added to the flattened array
if(is_array($item)) {
$foundAttributes = array();
foreach($item as $key=>$value) {
if(in_array($key, $keysToCheck) {
$foundAttributes[$key] = $value;
}
}
// we found at least one matching attribute
if(count($foundAttributes)) {
array_push($result, $foundAttributes);
}
// recursively go to the next level and merge the results from there
$result = array_merge($result, flattenArray($item, $keysToCheck);
}
}
return $result;
}
// usage example
$flattenedArray = flattenArray($originalArray, array('flag', 'qty'));
The above solution allows you to customise it for other type of objects, by passing different $keysToCheck arguments to the function.
If you also need the flattened array sorted, you can use usort() to achieve this.
Please pardon any syntax errors, I don't have a PHP interpreter at hand.

how to insert batch codeigniter

Ii everyone, I have an post data in array like this, I'm so confused how create the logic in controller:
POST Data:
Array
(
[nama_agenda] => blalala
[kilasan] => asdsadsadasd
[tgl_agenda] => 2014-06-01
[jam_agenda] => 13:27:30
[komisi] => Array
(
[0] => 1
[1] => 3
)
[fraksi] => Array
(
[0] => 1
[1] => 4
)
[badan] => Array
(
[0] => 1
[1] => 3
)
[anggota] => Array
(
[0] => 1
[1] => 4
)
[bagian] => Array
(
[0] => 2
[1] => 4
)
)
My question is how to insert into database, in controller? Thank's for help. I'll appreciate.
Since your structure is not well formed for insert_batch method. Your need to restructure it first. Consider this example:
$original_values = array(
'nama_agenda' => 'blalala',
'kilasan' => 'asdsadsadasd',
'tgl_agenda' => '2014-06-01',
'jam_agenda' => '13:27:30',
'komisi' => array(1, 3),
'fraksi' => array(1, 4),
'badan' => array(1, 3),
'anggota' => array(1, 4),
'bagian' => array(2, 4),
);
$new_values = array();
for($x = 0, $size = count($original_values['komisi']); $x < $size; $x++) {
foreach($original_values as $key => &$value) {
if(!is_array($value)) {
$new_values[$x][$key] = $value;
} else {
$new_values[$x][$key] = array_shift($value);
}
}
}
echo '<pre>';
print_r($new_values);
Should yield something like:
Array
(
[0] => Array
(
[nama_agenda] => blalala
[kilasan] => asdsadsadasd
[tgl_agenda] => 2014-06-01
[jam_agenda] => 13:27:30
[komisi] => 1
[fraksi] => 1
[badan] => 1
[anggota] => 1
[bagian] => 2
)
[1] => Array
(
[nama_agenda] => blalala
[kilasan] => asdsadsadasd
[tgl_agenda] => 2014-06-01
[jam_agenda] => 13:27:30
[komisi] => 3
[fraksi] => 4
[badan] => 3
[anggota] => 4
[bagian] => 4
)
)
Now you can use insert_batch() method.
$this->db->insert_batch('table_name', $new_values);
get all the data in array using $this->input->post() eg:
$bagian= $this->input->post('bagian');
and create a array()
$arr=array(
'db_table_col_1'=>$bagian,
'db_table_col_2'=>$post_data,
'db_table_col_2'=>$post_data
);
pass this array to model
$this->your_model_name->function_name($arr);
then in model create function
function_name($arg){
$this->db->insert('table_name',$arr);
}
if you want to insert multiple row then just use foreach
<?php
$arr1=array();
$arr= array(
'nama_agenda' => 'blalala',
'kilasan' => 'asdsadsadasd',
'tgl_agenda' => '2014-06-01',
'jam_agenda' => '13:27:30',
'komisi' => array
(
'0' => 1,
'1' => 3
),
'fraksi' => array
(
'0' => 1,
'1' => 4
),
'badan' => array
(
'0' => 1,
'1' => 3
),
'anggota' => array
(
'0' => 1,
'1' => 4
),
'bagian' => array
(
'0' => 2,
'1' => 4
)
);
foreach($arr as $row){
if(is_array($row)){
array_push($arr1,$row);
}
}
print_r($arr1);
and then pass this array to batch_insert
function_name($arr1){
$this->db->insert_batch('table_name',$arr1);
}
note arr1 syntax must be
$arr1 = array(
array(
'table_col1' => 'My title' ,
'table_col2' => 'My Name'
),
array(
'table_col1' => 'other title' ,
'table_col2' => 'other Name'
)
);
?>

Unset an multidimensional array by key

$series = array();
while($row = mysql_fetch_assoc($result)) {
$series[$row["data_id"]][] = $row;
}
The output from a print_r on $series yields for two example series:
Array (
[1] => Array ( [0] => Array ( [id] => 1 [data_id] => 1 [time_id] => 1
[data] => 1 ) [1] => Array ( [id] => 2 [data_id] => 1 [time_id] => 2
[data] => 3 ) )
[2] => Array ( [0] => Array ( [id] => 6 [data_id] => 2 [time_id] => 1
[data] => 7 ) [1] => Array ( [id] => 7 [data_id] => 2 [time_id] => 2
[data] => 4 ) )
My question: how do I unset the multidimensional array so it contains only [data] and none of the other keys? I still want $series to contain [1] and [2] but I do not want the respective sub-arrays to contain any other keys other than [data].
In fact, since I am reducing the subarrays to contain a single key, I would really like to get rid of the subarrays altogether so that I have two arrays:
$series[1] = array(1,3) and
$series[2] = array(7,4)
Try this :
$series = array();
while($row = mysql_fetch_assoc($result)) {
$series[$row["data_id"]][] = $row['data'];
}
I think you can loop in your array and build a new one keeping only data details
$array = array ('1' => array ( '0' => array ( 'id' => 1, 'data_id' => 1, 'time_id' => 1, 'data' => 1 ), '1' => array ( 'id' => 2, 'data_id' => 1, 'time_id' => 2, 'data' => 3 ), ),
'2' => array ( '0' => array ( 'id' => 6, 'data_id' => 2, 'time_id' => 1, 'data' => 7 ), '1' => array ( 'id' => 7, 'data_id' => 2, 'time_id' => 2, 'data' => 4 ) ));
$i= 0;
$n= 0;
$series = array();
foreach($array as $dato)
{
$series[$i] = array();
foreach($dato as $data)
{
foreach($data as $key => $value)
{
if($key == 'data')
{
$series[$i][$n] = $value;
$n++;
}
}
}
$n = 0;
$i++;
}
var_dump($series);
This will output
array (size=2)
0 =>
array (size=2)
0 => int 1
1 => int 3
1 =>
array (size=2)
0 => int 7
1 => int 4
Live demo

Multidimensional Array Find and Update The Value using PHP

I can't get suitable title for this thread (help me). I can't describe this problem so here the example of my problem.
My array :
Array ( [0] => Array ( [answer] => a [score] => 3 )
[1] => Array ([answer] => b [score] => 4 )
[2] => Array ( [answer] => h [score] => 3)
[3] => Array ( [answer] => a [score] => 4 ))
...
And I wanna get an output like this :
Array ( [0] => Array ( [answer] => a [score] => 7 )
[1] => Array ([answer] => b [score] => 4 )
[2] => Array ( [answer] => h [score] => 3))
...
You can see a change of score subkey in index key 0. This is happen because there is two value 'a' in answer subkey from index key 0 and 3. The score changed to 7 because of the sum of both (3+4). Really I don't have an idea for this, sorry for my english and thanks for help.
Feel free to comment. :)
$merged = array();
foreach ($array as $answer) {
if (isset($merged[$answer['answer']])) {
$merged[$answer['answer']]['score'] += $answer['score'];
} else {
$merged[$answer['answer']] = $answer;
}
}
var_dump($merged);
Check this answer, not using loop :
$arr = array ( array ( 'answer' => 'a', 'score' => 3 ),
array ( 'answer' => 'b', 'score' => 4 ),
array ( 'answer' => 'h', 'score' => 3),
array ( 'answer' => 'a', 'score' => 4 ));
$t = array_reduce($arr, function($result, $item) {
if(array_key_exists($item['answer'],$result)){
$result[$item['answer']] = array('answer' => $item['answer'], 'score' => $item['score']+$result[$item['answer']]['score']);
}
else{
$result[$item['answer']] = array('answer' => $item['answer'], 'score' => $item['score']);
}
return $result;
},array());
echo "<pre>";
print_r($t);
Output :
Array
(
[a] => Array
(
[answer] => a
[score] => 7
)
[b] => Array
(
[answer] => b
[score] => 4
)
[h] => Array
(
[answer] => h
[score] => 3
)
)
I though of using a temporary array:
/* Current array */
$array = array(
array("answer" => "a", "score" => 3),
array("answer" => "b", "score" => 4),
array("answer" => "h", "score" => 3),
array("answer" => "a", "score" => 4)
);
/* Using a temporary array */
$tmp_array = array();
foreach($array as $subarray){
if(array_key_exists($subarray["answer"], $tmp_array)){
$tmp_array[$subarray["answer"]] += $subarray["score"];
}else{
$tmp_array[$subarray["answer"]] = $subarray["score"];
}
}
/* Creating a new formatted array */
$new_array = array();
foreach($tmp_array as $key => $value){
$new_array[] = array("answer" => $key, "score" => $value);
}
print_r($new_array);

Categories