Jump to content


Newbie Coding Questions


  • You cannot reply to this topic
110 replies to this topic

#101 Cris D.

    Loves Etomite Forums!

  • Developers
  • PipPipPipPip
  • 1,104 posts
  • Gender:Male

Posted 13 June 2008 - 12:38 PM

I've been working on a problem using arrays now for over 3 months with slow and limited success. I'm hoping anyone can shed some light on what I am trying to accomplish...

I have a multi-dimentional array and am trying to extract specific processed information from it.

My example (the real example is more complex, but this highlights the crux of the problem):

$arr=array(
array('id'=>1, 'qty'=> 1, 'price'=> 2),
array('id'=>2, 'qty'=> 1, 'price'=> 3),
array('id'=>3, 'qty'=> 2, 'price'=> 4),
array('id'=>3, 'qty'=> 1, 'price'=> 3)
);

I want to extract the following things:
1) all unique values for 'id'
2) for each 'id' (qty * price)
3) for each unique id, the product of instances of 2).

the result from above should be:
array(
array['id']
(1,2,3), //all unique keys
array['product']//prooducts for each array of raw data
([0]=>2,
[1]=>3,
[2]=>8,
[3]=>3),
array['id_value']//the product of raw data for each unique instance of id
([1]=>2,
[2]=>3,
[3]=>11)
)

I have read and looked at examples of each php array function, but most don't handle multi-dimentional arrays, those that do, don't do what I am trying to accomplish except for applying user functions to array elements which I'm still tyring to get my head around- this looks like my best option at the moment.

I have tried writing an SQL statement that returns these results straight from the table without success (cross-row calculations prior to returning a $rs).

I have had most success with objects and methods, but I fear that if I continue down that path, my class is getting rediculously long-winded, and it is currently returning the array results I am trying to manipulate above.

I can write foreach() and if{}else statements building and re-building arrays but this is very slow and will kill my server if there are hundreds of thousands of records to process.

What is my best avenue to continue to persue this?

#102 Ralph

    Loves Etomite Forums!

  • Admin
  • 6,524 posts
  • Gender:Male

Posted 13 June 2008 - 02:07 PM

I have encountered similar situations, Cris, and have reverted to using a loop to handle the data manipulations... I've used for(), foreach(), while() combined with array functions, and maybe even a few other, more obscure, solutions... However you decide to do it, try to use a few iterations and calculations as possible... The available PHP functions just don't address enough real world possibilities and using multiple array functions to achieve results can be far slower than simply using loops...

#103 Randy

    Likes Etomite Forums!

  • Member
  • PipPip
  • 309 posts

Posted 13 June 2008 - 10:19 PM

Hi Cris,

I'm on a gig in NYC right now so don't have a lot of time to respond until next week. But frankly don't see the big deal here. Please note I restructured your array slightly to accommodate your goal. Maybe I'm missing something but here is your answer...

$arr=array(

array('id'=>1, 'prod'=>array('qty'=> 1, 'price'=> 2)),

array('id'=>2, 'prod'=>array('qty'=> 1, 'price'=> 3)),

array('id'=>3, 'prod'=>array('qty'=> 2, 'price'=> 4)),

array('id'=>3, 'prod'=>array('qty'=> 1, 'price'=> 3))

);
echo '<pre>';
print_r(array_unique(array_keys($arr)));
foreach($arr as $lvl1){
echo "Product of qty and price for ".$lvl1['id']."= ".$lvl1['prod']['qty']*$lvl1['prod']['price'].'<br />';
}


Two Lines....No multiple foreach()'s etc. What did I miss?

Anyway, let me know if this doesn't work for you,

Randy.

#104 Cris D.

    Loves Etomite Forums!

  • Developers
  • PipPipPipPip
  • 1,104 posts
  • Gender:Male

Posted 14 June 2008 - 11:11 AM

Nice try Randy. Your code returns the following:
Array
(
[0] => 0
[1] => 1
[2] => 2
[3] => 3
)
Product of qty and price for 1= 2
Product of qty and price for 2= 3
Product of qty and price for 3= 8
Product of qty and price for 3= 3
As you can see, there are two distinct values being returned for id=3 whereas I am tring to get all unique keys to process a single product for multiple instances of id (complicate this by adding the ability to get data from 2 tables, according to a range of value tests.

I have spent all day on it and have come up with a (quite messy but flexible) solution using a combination of OOP, sql, loops and php functions.

//return a complete array of data for a single given book from mulitple tables
public function getMyStatusBookSingleOrder($id,$status){
global $etomite;
	   
		  $sql = " SELECT pd_id, od_id, od_qty, od_status, od_internalKey, id, title
				   FROM ".$etomite->db."tbl_order_item AS oi
				   INNER JOIN ".$etomite->db."book_manager AS bm
				   ON oi.pd_id = bm.id
				   WHERE oi.od_status = '".$status."' 
				   AND oi.od_internalKey='".$this->author."'
				   AND oi.pd_id = '".$id."'";

		   $row = $etomite->dbQuery($sql);
		   $rs = $etomite->fetchRow($row);
		   
return $this->bookSingleOrder = $rs;

}
//return an array for a set book from order table only
public function getPaidBookValue($id){
global $etomite;
	   
		   $sql = "SELECT * FROM ".$etomite->db."tbl_order_item 
		   WHERE pd_id ='".$id."'
		   AND od_internalKey = '".$this->author."'
		   AND od_status = 'Paid'";
		   
		   $row = $etomite->dbQuery($sql);
		   $rs = $etomite->fetchRow($row);
	 return $this->paidBooks = $rs;	  
}
	  
//get subtotals for each id
public function dataStreamPaidTotals(){
  $rs=$this->getMyPaidBooks();
  for($i=0; $i<count($rs); $i++){
	$totals[] = $this->getPaidBookValue($rs[$i]['pd_id']);
  }
  return $this->totals=$totals;
}

//do product calculations
public function bookDataViews($id,$switch){
		   
	 $rs=$this->getPaidBookValue($id);
		extract($rs);
	 if($switch == 'subtotal'){
		   $subTotal += $od_qty * $od_price;	 
	  return $this->subtotal = $subTotal;
	  }

and implemented the class and data stream by...
$a=new bookSpotUser();
$recs = $a->dataStreamPaidTotals();

   for($i=0; $i<count($recs); $i++)
   {
	   $book=$a->getMyStatusBookSingleOrder($recs[$i]['pd_id'], $status);
	   $total=$a->bookDataViews($recs[$i]['pd_id'],'subtotal');
	   $data[$book['title']]=$total;
   }

return $data;

returns:
array('title1'=>$value, 'title2'=>$value);
Like I said...long-winded! I'm really surprised that there isn't a "get all the unique keys from a field of my choice from this multi-dimentional array" function. It would probably be called:array_intersect_uassoc_key_exists_merge_recursive. Maybe in PHP6?

#105 Randy

    Likes Etomite Forums!

  • Member
  • PipPip
  • 309 posts

Posted 14 June 2008 - 01:43 PM

I read this far...

I want to extract the following things:
1) all unique values for 'id'
2) for each 'id' (qty * price)

You have that with what I've given you (The way I label them is purely irrelevant)...

3) for each unique id, the product of instances of 2).

In your explanation for item three, you say "the product of..." but in the your sample answer you've "added" 8 + 3 to get 11. So I'll assume you want all the products of duplicated 'IDs' ADDED together rather than MULTIPLIED as the word PRODUCT means.

 $arr=array( 
		   array('id'=>1, 'prod'=>array('qty'=> 1, 'price'=> 2)),
		   array('id'=>2, 'prod'=>array('qty'=> 1, 'price'=> 3)),
		   array('id'=>3, 'prod'=>array('qty'=> 2, 'price'=> 4)),
		   array('id'=>3, 'prod'=>array('qty'=> 1, 'price'=> 3))			
);
echo '<pre>';
print_r(array_unique(array_keys($arr)));
$count = 1;
foreach($arr as $lvl1){
	if($previous_id && $previous_id == $lvl1['id'] ) {
		   $temp += $lvl1['prod']['qty']*$lvl1['prod']['price'];
		   $count++;
			echo "id ( ".$lvl1['id']." ) was duplicated ".$count." times, the total value of all the qty*prices for id ( ".$lvl1['id']." ) so far is = ".$temp."<br />";
	} elseif($previous_id) {
		echo "id ( ".$previous_id." ) was not duplicated, the total value of the qty*price for id ( ".$previous_id." ) is = ".$temp."<br />";
		$temp=0;
	}else {
	}
	$temp += $lvl1['prod']['qty']*$lvl1['prod']['price'];
	$previous_id = $lvl1['id'];
}

OK...had to work for this one a little bit. But here you go. Again, the output is just not relavent -- you can formulate it any way you want to. I'll go back and look at your post again as I'm sure there is something else I'm oversimplifying here.

Randy

#106 Randy

    Likes Etomite Forums!

  • Member
  • PipPip
  • 309 posts

Posted 14 June 2008 - 01:45 PM

Yup, Looks like that should do it for you!

Hope so anyway. Let me know.

Randy

#107 Cris D.

    Loves Etomite Forums!

  • Developers
  • PipPipPipPip
  • 1,104 posts
  • Gender:Male

Posted 14 June 2008 - 11:50 PM

Quote

I'm sure there is something else I'm oversimplifying here

You've not oversimplified it, it's perfect. After seeing your code, I realise what I was having difficulty with...
foreach($arr as $lvl1){
	if($previous_id && $previous_id == $lvl1['id'] ) {

It's using a non-existant variable in an argument that has not been assigned a value yet. That chicken or egg scenario does my head in!
Thanks for working on this one Randy. I never expect anyone to write my code for me, just to give hints when I get stuck, but I do appreciate it... :im Not Worthy: ...above and beyond the call of duty.

#108 Randy

    Likes Etomite Forums!

  • Member
  • PipPip
  • 309 posts

Posted 15 June 2008 - 12:28 AM

Not at all Cris, we all get blinded by the code we've looked at for too long. That's all this looks like to me. There is probably ten different ways to accomplish this task. I just hacked this together quickly to try to solve your problem with a succinct bit of code.

You are one person that I always trust has tried in earnest to figure things out before you ask for someone to help. I don't see this as "writing your code"...just as helping. Glad we got this step figured out.

Randy

#109 Cris D.

    Loves Etomite Forums!

  • Developers
  • PipPipPipPip
  • 1,104 posts
  • Gender:Male

Posted 09 August 2008 - 10:06 AM

I am considering writing an error handling module that can be used within etomite across snippets.

I have quite a large site now that uses 71 (at last count) snippets of various sizes and all the error handling and outputting is done from within each snippet. Some of the error handling outputs in arrays, some in strings, some are already marked up, some requiring markup. It is becomingly increasingly difficult to bring it together and maintain. I am looking at ways to use a standard error handling method that can be used throughout the code.
Error handling for me means:
Unexpected code logic errors, default message errors, validation errors (if not caught by java pop-ups), configuration errors, and user-warnings. The validation error handling re-use would be good and it would significantly reduce the size of many snippets. Most of the errors will be user-generated and therefore should look like part of the site, so they must be generated during output buffering.

What would be the preferred method of making a module (or class) like this avaliable across snippets- and withstand regular use of runSnippet and stand the best chance of success through page caching? Should I be planning to throw the functions into the global namespace? Storing the error messages in session variables? Loading the class through the parser (like the newFormClass)? Some other method I've not considered? Php error handling seems very clunky and inflexible unless I've misunderstood it.

Ideally I'd love to be able to go something like:
$data=array();
$data['errors'][]=$errorClass->validate($field,$validationChars,$errorMessage['nn']);
$output .=$etomite->parseChunk($errorChunk,$data, '{','}');
or
$_SESSION['error'][]=validate($field,$validationChars,$errorMessage['nn']);
if($_SESSION['error']) return $etomite->parseChunk($errorChunk,$_SESSION['error']);

Any guidance in the right direction here would be great.

#110 Ralph

    Loves Etomite Forums!

  • Admin
  • 6,524 posts
  • Gender:Male

Posted 09 August 2008 - 02:11 PM

For custom error handling I'd suggest looking at how the Etomite parser and Etomite manager handle errors currently, and perhaps compare those methods with several of the currently available error handler classes... Any large coding project could benefit from a central yet customizable error handler, and those coded in Etomite are no exception...

#111 jon

    Etomite Forum Newbie

  • Member
  • 39 posts

Posted 09 August 2008 - 09:30 PM

When I started with Etomite almost a year ago, I quickly discovered the need to standardize Error Handling in Snippets. Best I came up with was standardizing the Calling Sequence to "Internal Snippets" -- those snippets I call with runSnippet from other snippets.

All my Internal Snippets return an array that begins with a variable named error as in the following example:
return array("error" => "", "host" => $host,"user" => $user,"password" => $password);
In turn, in all my snippets, after each runSnippet call to an Internal Snippet, I check the error variable. If it is a zero length character string, all is well. Otherwise, it contains an error message, which I standardized to begin "Error in {snippet name}: ", as in the following example:
return array("error" => "Error in $snippet: getIntTableRows failed accessing Table admin_db.");
The external snippets display either the properly formatted information requested, or the error message, as in the following example:
   $output = $etomite-> runSnippet("DBPopulateChunk",
	 $params=array(
	   "rs" => $rs,
	   "chunk" => "$chunk",
	   "tag" => "$htmltag"
	   )
	 );
   if ($output["error"] == "") {
	return $output["output"];
   } else {
	return $output["error"];
   };
Any errors in the External Snippet do an immediate return with the error message, as in the following example:
return "Error in $snippet:  invalid value ('$secure') for optional (default is yes) secure= parameter.  Valid values are:  yes no.";






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users