Comparing two arrays of objects and replacing values - php

I have 2 arrays of objects in a e-commerce project (built in Code Igniter), one an array of product objects and one an array of sale item objects, with product id's and the amount of discount. I need to compare the arrays so I can put a new price in the items which are on sale, but I cannot seem to code the loops properly. Here is my current code:
private function checkSalesProducts($query) { //$query is an array of product objects
$this->db->select("sale_product, sale_discount");
$salesItems = $this->db->get("sale_items");
foreach($salesItems->result() as $salesItem)
{
for($i=0; sizeof($query); ++$i)
{
if($salesItem->sales_product == $query[$i]->prod_id)
{
$query[$i]->prod_price = $query[$i]->prod_price * (1 - $salesItem->sales_discount);
$query[$i]->sale_item = true;
break;
}
}
}
echo "<pre>";
print_r($query);
echo "</pre>";
}
Any ideas?

Your for() should be
for($i = 0; $i < sizeof($query); $i++)
Your script should freeze at the moment since you tell it to loop while sizeof($query) > 0, which it always have since you don't modify it in the loop.

Related

Forget not modifying the original collection Laravel 5.7

I'm attempting to to remove random elements from a collection while iterating through a for loop. The idea is that each time it goes through the for loop, the items in the collection available doesn't include items found and removed in previous iterations. I've attempted to use forget on the initial collection, but i'm still finding doubles in the results. Any help would be appreciated, thanks!
$data = SomeModel::get();
for($i = 1; $i <= $max; $i++) {
$random = $data->random($numberToPick);
foreach($random as $option) {
$data->forget($option->id);
}
}
I dd($data) at the end, and do indeed see the items selected are removed from the final collection, but as mentioned, i'm still getting some randoms that have keys matching previous iterations.
The problem here is that forget will remove the item by its index. You are giving as argument the id of the object inside the collection, but its index is not the same as the id.
Try this:
$data = SomeModel::get()->keyBy('id');
for($i = 1; $i <= $max; $i++) {
$random = $data->random($numberToPick);
foreach($random as $option) {
$data->forget($option->id);
}
}

Array Filter and Array Values taking a long time on large PHP array of objects

I have a piece of code running a simulation.
public function cleanUpHouses(\DeadStreet\ValueObject\House\Collection $collection)
{
$houses = $collection->getHouses();
$housesLength = count($houses);
$filterValues = false;
for($i = 0; $i < $housesLength; $i++) {
if(!$this->houseModel->hasBeenAttacked($houses[$i])) {
break;
}
$houses[$i]->setCurrentAttackers(0);
if($this->houseModel->requiresDestroying($houses[$i])) {
$houses[$i] = null;
$filterValues = true;
}
}
if($filterValues) {
$houses = array_values(array_filter($houses));
}
$collection->setHouses($houses);
return $collection;
}
However, $collection contains an array ($getHouses) of up to and over 1 million results, although it will never need to iterate over all of these results, the line $houses = array_values(array_filter($houses)) is taking ages due to the sheer size of the array, (up to 3 seconds each time this line is ran).
I have to keep the array index numeric, and there can be no null values in this array.
I was hoping unset($array[$i]) would shift the array elements after the element being unset 'down' in key, so if I was to unset($array[5]), then $array[6] would become $array[5], however it doesn't seem to work like this.
The break conditional is there because, on an iteration if the house under iteration hasn't been attacked, then it's safe to assume any other house after that in the array has also not been attacked.
Is there an optimal, less resource heavy way to achieve this?
I can't really restructure this at the moment as it's in unit tests and I need it finishing ASAP, the approach isn't great, but eh.
I think the most painless way to achieve this is something like this:
While you are looping through the array of houses, and you need to unset something in the array, you can cheat the loop itself.
if($this->houseModel->requiresDestroying($houses[$i])) {
// $houses[$i] = null;
// when you unset the $i house in the array,
// you can simply switch it with the last one in the array, keeping in mind,
// that this may break your logic with the break condition, so will want to change that as well.
$lastHouse = $houses[$housesLength - 1];
$houses[$i] = $lastHouse;
unset($houses[$housesLength - 1]);
$i--;
$housesLength--; // by doing the top two lines we would make the loop check the last house again.
$shouldBreak = false; // this will keep your logic with the break if later.
// $filterValues = true; // you can remove this line here.
}
You would want to set up a variable for the break condition before the for loop starts.
$shouldBreak = true;
for($i = 0; $i < $housesLength; $i++) {
...
And now for the condition itself
if(!$this->houseModel->hasBeenAttacked($houses[$i]) && true === $shouldBreak) {
break;
} else {
$shouldBreak = true; // we set $shouldBreak = false when we unset the last house,
// so we would want to keep checking the houses not to break the logic.
}
We only will remove the last element in the array, so it will be kept numeric.

Delete the whole row from an array in php

How do I delete the whole line from an array? When the delete-button is pressed it should delete the whole line.
my array looks like that:
$liste[0][0] = email-user1
$liste[0][1]= password-user1
$liste[1][0] = email-user2
$liste[1][1]= password-user2
So if I delete the user one, the user2 should just take the place from user1(which should just disappear).
if (isset($_GET['delete'])){
$id=key($_GET['delete']);
for ($i = 0; $i < count($liste); $i++){
if ("$i"=="$id"){
unset($liste[$id][0]);
unset($liste[$id][1]);
unset($liste[$id][2]);
}
else{
}
}
update
I'm using array_splice($liste, $id, 1); now but everytime I try to save it to the file I get an error: implode(): Invalid arguments passed. For saving it to the file, I use the following function:
function saveDataToFile($fileName, $liste){
$file=fopen($fileName,"w");
for ($i = 0; $i < count($liste); $i++) {
$zArray=$liste[$i];
$zeile=implode("|", $zArray);
if(strlen($zeile) > 0){
$zeile=$zeile."\r\n";
fwrite($file, $zeile);
}
}
fclose($datei);
}
Try the below code:
$liste[0][0] = "email-user1";
$liste[0][1]= "password-user1";
$liste[1][0] = "email-user2";
$liste[1][1]= "password-user2";
$liste[2][0] = "email-user3";
$liste[2][1]= "password-user3";
unset($liste[1]); // say you want to delete this row
$new_arr = $liste;
unset($liste);
$i=0;
foreach($new_arr as $value){
$liste[$i] = $value;
$i++;
}
You can use array_splice() method:
array_splice($liste, $id, 1);
$liste[0][0], $liste[0][1] and $liste[0][2] are in real nothing else than a value array(value, value, value) (the inner array) which is assigned to $liste[0] (the outer array)
unsetting this (outer) array value $liste[0] is enough:
unset($liste[$id]);
If you care about the keys of this array (I see you loop from 0..n), you need to reindex your array using:
$liste = array_values($liste);
This will make your array behaving more like arrays normally do in other programming languages
Good practice is to use foreach instead of for. In this case you don't need to reindex:
for ($liste as $key=>$value){
if ("$key"=="$id"){
unset($liste[$key]);
}
But anyway you don't have to loop through an array just for finding a key. It's enough doing this:
if (isset($liste[$id])) { /* optional: check if the key exists */ }
unset($liste[$id]);

Sorting objects in array

I have an array of objects containing a number of values. The values are set correctly and the data inside this array is also shown in correct way accoring to the order of objects.
What i would want now ii that the order is changed. In this particular example according to the objects 'Point' value, so the objects with the highest Pointvalue is first and so on...
What I tried to do was finding the object with the highest value, push it in the array and unsetting the original value. And with array_slice getting the relevant array elements in the end.
I also succeeded in the first part, but the problem is I keep finding the same object, so i somehow doesn't remove it from the array.
$max = $obj[0];
for ($j =0; $j<count($obj)-$j; $j++) {
for ($i=0; $i<count($names); $i++) {
if ($max->Point < $obj[$i+1]->Point) {
$max = $obj[$i+1];
}
}
if ($max->id == $obj[$j]->id) {
unset($obj[$j]);
}
array_push($obj, $max);
}
I'm not sure you can see through the code and what I'm trying to do, but hopefully someone can and either show my mistake(s), or show others way to accomplish the same?
Try using the usort() function. It allows you to sort the array according to a comparison function that you define.
function lower_points($a, $b) {
if ($a->Point == $b->Point) return 0;
else if ($a->Point > $b->Point) return -1;
else return 1;
}
usort($array_of_objects, lower_points);

Save key's and post meta data into array's - Wordpress

Im using wordpress as my base and I need to output the post meta for all my posts, but only for a certain number of keys.
What I intend to do is to save a list of all my keys, that im going to use to query wordpress for metadata for that post.
Below is my code.
//HERE YOU CAN SEE THE KEYS IMM USING ATM
$nyckellista[] = array("ebutik_allm_bas_operativsystem" ,"--foretagsform"
,"ebutik_allm_bas_omsättning");
$i = 0;
//Here im trying to query the get_post_meta with my keys and save the result (it's an array aof values that it return)
foreach($nyckellista as $nyckel)
{
$nyckellista[$i] = get_post_meta($post->ID,$nyckel,false);
echo $i . "Nyckel:" . $nyckel[$i];
$i++;
}
//HERE ME TRYING TO PRINT THE ARRAY CONTENTS
$count = count ($nyckellista);
echo $count;
for($y=1; $y <= $count; $y++)
{
$countmore=count($nyckellista[$y]);
for($x=1; $x <= $countmore; $x++)
{
print ($nyckellista[$y][$x] . "<br> ");
}
echo "<br>";
}
WHAT AM I DOING WRONG?
In the first line the $nyckellista variable is being declared implicitly as an array and then you're assigning to its first position an array of values.
Is this what you need/intend?
Edit:
Another point is, in the counts area of the code, that php arrays get numeric indexes starting at 0, not at 1 (see Example #4 in PHP array reference)

Categories