Forum Moderators: coopster

Message Too Old, No Replies

Merging arrays

         

technossomy

10:54 pm on Nov 9, 2005 (gmt 0)

10+ Year Member



Suppose I have two arrays of prices given by date, but not all prices are present on every date:

$p1 = array(0 => array('date'=>1, 'p1'=>4000), 1 => array('date'=>2, 'p1'=>3900), 3 => array('date'=>4, 'p1'=>3800));

$p2 = array(0 => array('date'=>1, 'p2'=>40), 2 => array('date'=>3, 'p2'=>41), 3 => array('date'=>4, 'p2'=>42));

and when merging these arrays as such:

print_r(array_merge_recursive($p1, $p2));

yields:

Array (
[0] => Array ( [date] => 1 [p1] => 4000 )
[1] => Array ( [date] => 2 [p1] => 3900 )
[2] => Array ( [date] => 4 [p1] => 3800 )
[3] => Array ( [date] => 1 [p2] => 40 )
[4] => Array ( [date] => 3 [p2] => 41 )
[5] => Array ( [date] => 4 [p2] => 42 )
)

but what I would like is this:

Array (
[0] => Array ( [date] => 1 [p1] => 4000 [p2] => 40 )
[1] => Array ( [date] => 2 [p1] => 3900 )
[2] => Array ( [date] => 3 [p2] => 41 )
[3] => Array ( [date] => 4 [p1] => 3800 [p2] => 42 )
)

ie for every date all available prices even if there is only one. Is there a PHP function which achieves that?

Thanks in advance

Tech

NomikOS

11:56 pm on Nov 9, 2005 (gmt 0)

10+ Year Member



stay close, you give me an excelent opportunity for learn about this function: array_merge_recursive

(so many times ignored by myself for looks a little hard to use. but I love arrays, so...)
---

NomikOS

12:21 am on Nov 10, 2005 (gmt 0)

10+ Year Member



meanwhile why don't you take a look about this different manner of construct your arrays?


foreach ($dates as $date)
{
$prices = $query("someQueryDQLForPricesWhere_date=$date");
$i = 0;
foreach ($prices as $price)
{
$priceArray[$date][++$i] = $price;
}
}

this give you arrays like:


$priceArray['date_1'][1] = 4000;
$priceArray['date_1'][2] = 40;
$priceArray['date_2'][1] = 3900;
$priceArray['date_3'][1] = 41;
# etc...

exactly what you want:
>> for every date all available prices even if there is only one.

---

NomikOS

2:43 am on Nov 10, 2005 (gmt 0)

10+ Year Member



any body here?
----------

Yours arrays of prices are not well defined. you did it at hand, right?
I say it because for one date you have p1 and p2 (that suggest 2 types of currencies, not 2 prices differents)
To have what you want, you should use something as what suggested in msg #3.

correction:
----------
someQueryDQLForPricesWhere_date=$date -> some_SQL_QueryForPricesWhere_date=$date

Anyway, i can say that array_merge_recursive do exactly what his name says...

byte
:P

---

technossomy

6:50 am on Nov 10, 2005 (gmt 0)

10+ Year Member



Hi NomikOS

Thanks for your suggestion, I will try that and get back to you at the soonest. I was indeed thinking of using a database which will probably be detrimental to overall performance, because there are thousands of prices. This is a whole topic in itself: arrays or db tables?

Nonetheless, I'll stick to arrays for the moment, because the resulting array needs to be flushed to a graph.

Best

Tech

grandpa

7:20 am on Nov 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



technossomy, is this what you want to do..

$new_arr = (array_merge_recursive($p1, $p2));
asort($new_arr);
print_r($new_arr);

Here are the results.

Array
(
[0] => Array
(
[date] => 1
[p1] => 4000
)

[3] => Array
(
[date] => 1
[p2] => 40
)

[1] => Array
(
[date] => 2
[p1] => 3900
)

[4] => Array
(
[date] => 3
[p2] => 41
)

[2] => Array
(
[date] => 4
[p1] => 3800
)

[5] => Array
(
[date] => 4
[p2] => 42
)
)

NomikOS

8:19 am on Nov 10, 2005 (gmt 0)

10+ Year Member



grandpa:
You obtain the same 6 records only in a different order! i think that $p1 and $p2 are not apropriate like arguments to array_merge_recursive because there is not a direct relation between a date to various prices as should be debt his names (p1 and p2 and date, ie: one var called date and 2 vars for price, should be only one!)...
What do you think?

technossomy:
Seems that you are very concern about SQL performance, so...

please, can any of you (preferably both), give me an advice here:

[url=http://www.webmasterworld.com/forum112/134.htm]innoDB v/s MyISAM[/url]
? I'm about to migrate to innoDB. And I need more confidence for that.

TIA, NomikOs ¦-)

---

grandpa

8:56 am on Nov 10, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



is this what you want to do..

ahem.. of course not. After reading your post again I decided to give it another try. Be advised, this is probably ugly as heck, so before you look at the code, here are the results. (Still not exactly what you wanted)

Array
(
[1] => Array
(
[date] => 1
[0] => p1
[1] => 4000
[2] => p2
[3] => 40
)

[2] => Array
(
[date] => 2
[0] => p1
[1] => 3900
)

[3] => Array
(
[date] => 3
[0] => p2
[1] => 41
)

[4] => Array
(
[date] => 4
[0] => p1
[1] => 3800
[2] => p2
[3] => 42
)
)

OK, so are you sure you want to see this code?

$new_arr = (array_merge_recursive($p1, $p2));
asort($new_arr);
foreach($new_arr as $key => $val) {
foreach($val as $key2 => $val2) {
if ($key2 == 'date') {
if ($_val2 <> $val2) {
$_val2 = $val2;
$newer_arr[$_val2] = array('date'=>$val2);
}
}
else {
array_push($newer_arr[$_val2],$key2,$val2);
}
}
}

technossomy

10:18 am on Nov 10, 2005 (gmt 0)

10+ Year Member



Hi grandpa

Thanks for your input, and your suggestions are welcome. My goal is to have an array that is "table-ready", ie looks like a selection from a relational table, and may contain null-values. I have no need to indicate whether it concerns p1 or p2 type prices.
If there is no standard PHP function that does this, then a sort combined with a combined traversal as ypou suggest may be my only option.

I'll get cracking on this as well, to see what comes up.

NomikOS: MySQL is what I am using indeed, and it is known to be very fast. My prime concern is performance, so I like to keep everything in memory and work on it there.

Hope this helps and thanks again for your help

Tech

jatar_k

4:50 pm on Nov 10, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



$p4 = array_merge($p1, $p2); 
array_multisort($p4);
$counter = 0;
$last = null;
$newp = array();
while (is_array($p4[$counter])) {
if ($p4[$counter]['date'] == $last) {
if (isset($p4[$counter]['p1'])) {
$newp[count($newp)-1][] = $p4[$counter]['p1'];
} else {
$newp[count($newp)-1][] = $p4[$counter]['p2'];
}
} else {
if (isset($p4[$counter]['p1'])) {
$newp[] = array($p4[$counter]['date'],$p4[$counter]['p1']);
} else {
$newp[] = array($p4[$counter]['date'],$p4[$counter]['p2']);
}
$last = $p4[$counter]['date'];
}
$counter++;
}
echo '<p><pre>';
print_r($newp);
echo '</pre>';

it works, it's dirty I really hate havin to test for multiple keys.

NomikOS

12:39 am on Nov 11, 2005 (gmt 0)

10+ Year Member



i'am out of the the world..
i want read what you write , at first time i like it...

----

technossomy

8:09 am on Nov 12, 2005 (gmt 0)

10+ Year Member



jatar_k

Thanks for your assistance, but the result is incorrect. Where it says:

Array
(
...
[2] => Array
(
[0] => 3
[1] => 41
)

...

)

it should say:

Array
(
...
[2] => Array
(
[0] => 3
[2] => 41
)
...

)

I'll continue to work on this as well.

Best wishes

Tech

technossomy

8:58 am on Nov 12, 2005 (gmt 0)

10+ Year Member



Because of the deadline I have, I decided to go for a database solution after all and using JOINs and "WHERE EXISTS" to get to a result set.

Thanks again

Tech

jatar_k

3:02 pm on Nov 12, 2005 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



if all you need is to push it over one if it is a p2 key you can do that in the else

$newp[count($newp)-1][] = $p4[$counter]['p2'];

I just used next [] but you could set it to 2

$newp[count($newp)-1][2] = $p4[$counter]['p2'];

no big thing