Reputation: 2299
I have a ton of parsed XML records that are related by two attributes: id
and rid
.
These XML records, when parsed, create the following (example) PHP array:
Array(
'master' => array(
[0] => array( 'id' => 123, 'info' => 'hello' ),
[1] => array( 'id' => 456, 'info' => 'world' )
),
'tbl-ex' => array(
[0] => array( 'rid' => 123, 'test' => 'aye', 'num' => 88 ),
[1] => array( 'rid' => 123, 'test' => 'bbb', 'num' => 99 ),
[2] => array( 'rid' => 456, 'test' => 'zzz', 'num' => 102, 'o' => 'h')
),
'tbl-ey' => array(
[0] => array( 'rid' => 456, 'mama' => 'mia' ),
[1] => array( 'rid' => 123, 'oof' => 'foo' )
),
'tbl-ez' => array(
[0] => array( 'rid' => 123, 'stop' => 'wegetit', 'ok' => 1 ),
[1] => array( 'rid' => 456, 'finally' => 'done' )
)
);
When I parse this, I want all records under master
to be returned on the condition that id == rid
, in this format:
Array(
[0] => array(
'master' => array( 'id' => 123, 'info' => 'hello' ),
'tbl-ex' => array(
[0] => array( 'test' => 'aye', 'num' => 88 ),
[1] => array( 'test' => 'bbb', 'num' => 99 )
),
'tbl-ey' => array(
[0] => array( 'oof' => 'foo' )
),
'tbl-ez' => array(
[0] => array( 'stop' => 'wegetit', 'ok' => 1 )
)
),
[1] => array(
'master' => array( 'id' => 456, 'info' => 'world' ),
'tbl-ex' => array(
[0] => array( 'test' => 'zzz', 'num' => 102, 'o' => 'h' )
),
'tbl-ey' => array(
[0] => array( 'mama' => 'mia' )
),
'tbl-ez' => array(
[0] => array( 'finally' => 'done' )
)
)
);
This seems obvious (and works):
$ret = array();
$init_record = $original_array['master'];
$records_to_merge = $original_array;
unset($records_to_merge['master']);
$i = 0;
foreach($init_record as $master_index => $master){
$current_id = $master['id'];
foreach($records_to_merge as $record_type => $record_array){
foreach($record_array as $index => $record){
if($current_id == $record['rid']){
$ret[$i]['master'] = $master;
$ret[$i][$record_type] = $record;
$i++;
}
}
}
}
This works, but since I have a ton of records (and a lot more data), it's excruciatingly slow.
I then tried to use an array_filter
with a callback function that evaluates the $record
, followed by the index rid
being equal to the $master_id
. This however filters out the matching record, and not the entire array it is contained in. So I just get a bunch of matching rid
's in my array but no other data.
Is there some fast, easy way that I'm overlooking right now?
Upvotes: 1
Views: 51
Reputation: 2644
Here's a solution that has only one nested foreach
instead of two. I'm not sure if it will make a difference since every element of the array is iterated through. It makes one change in the structure of the new array: the outer array is associative instead of just indexed. The order should be preserved, though.
php > $original = array(
php ( 'master' => array(
php ( array( 'id' => 123, 'info' => 'hello' ),
php ( array( 'id' => 456, 'info' => 'world' )
php ( ),
php ( 'tbl-ex' => array(
php ( array( 'rid' => 123, 'test' => 'aye', 'num' => 88 ),
php ( array( 'rid' => 123, 'test' => 'bbb', 'num' => 99 ),
php ( array( 'rid' => 456, 'test' => 'zzz', 'num' => 102, 'o' => 'h')
php ( ),
php ( 'tbl-ey' => array(
php ( array( 'rid' => 456, 'mama' => 'mia' ),
php ( array( 'rid' => 123, 'oof' => 'foo' )
php ( ),
php ( 'tbl-ez' => array(
php ( array( 'rid' => 123, 'stop' => 'wegetit', 'ok' => 1 ),
php ( array( 'rid' => 456, 'finally' => 'done' )
php ( )
php ( );
php >
php > //$merge = $original;
php > //unset($merge['master']);
php > unset($pointer);
php >
php >
php > foreach($original as $tbl => $data) {
php {
php { foreach($data as $row) {
php { if($tbl=='master') {
php { $pointer[$row['id']]['master'] = $row;
php { continue;
php { }
php { $pointer[$row['rid']][$tbl][] = $row;
php {
php { }
php {
php { }
php >
php > print_r($pointer);
Array
(
[123] => Array
(
[master] => Array
(
[id] => 123
[info] => hello
)
[tbl-ex] => Array
(
[0] => Array
(
[rid] => 123
[test] => aye
[num] => 88
)
[1] => Array
(
[rid] => 123
[test] => bbb
[num] => 99
)
)
[tbl-ey] => Array
(
[0] => Array
(
[rid] => 123
[oof] => foo
)
)
[tbl-ez] => Array
(
[0] => Array
(
[rid] => 123
[stop] => wegetit
[ok] => 1
)
)
)
[456] => Array
(
[master] => Array
(
[id] => 456
[info] => world
)
[tbl-ex] => Array
(
[0] => Array
(
[rid] => 456
[test] => zzz
[num] => 102
[o] => h
)
)
[tbl-ey] => Array
(
[0] => Array
(
[rid] => 456
[mama] => mia
)
)
[tbl-ez] => Array
(
[0] => Array
(
[rid] => 456
[finally] => done
)
)
)
)
php >
Upvotes: 1