I have two arrays which are populated from two separate api requests.
protected $playerDetails = ['name' => [], 'role' => [], 'donations' => [], 'donationsReceived' => [], 'lastSeen' => []];
protected $warDetails = ['name' => [], 'warCollectionBattles' => [], 'warCardsEarned' => [], 'allocatedFinalBattles' => [], 'numberOfFinalBattlesPlayed' => [], 'warFinalBattleWin' => []];
Originally I had these 2 separate arrays as the data returned from both api requests has different indexes but as they share a common value name I am trying to refactor both arrays into one array.
protected $playerDetails = ['name' => [], 'role' => [], 'donations' => [], 'donationsReceived' => [], 'lastSeen' => [], 'warCollectionBattles' => [], 'warCardsEarned' => [], 'allocatedFinalBattles' => [], 'numberOfFinalBattlesPlayed' => [], 'warFinalBattleWin' => []];
So far I have the following code, which is working up until I try to assign $this->playerDetails['warFinalBattleWin'] but I am uncertain to why this isn't assigning like any other variable would be assigned.
//gets the index of the playerDetails aray
for ($i = 0; $i <= count($this->playerDetails); $i++) {
//gets the index of the data from the api response
for ($x=0; $x <= count($warArr['participants'])-1 ; $x++){
//this outputs the name and wins as expected
echo $warArr['participants'][$x]['name'] ;
echo $warArr['participants'][$x]['wins'] . "<BR>";
//checks that the name from the playerDetails array matches the name from the api response at each index
if($this->playerDetails['name'][$i] == $warArr['participants'][$x]['name']){
$this->playerDetails['warFinalBattleWin'][$i] = $warArr['participants'][$x]['wins'];
}
}
break;
}
//this outputs an empty array
print_r($this->playerDetails['warFinalBattleWin']);
Also would someone be able to explain why on this line
for ($x=0; $x <= count($warArr['participants'])-1 ; $x++){
I have to subtract 1 from the count of the array? If I don't do this I get an undefined offset notice such as
Undefined offset: (value of count($warArr['participants']) )
In the first for loop where I was getting the index for each player from the playerDetails array I was getting the count of the first dimension of this array when I should have been using count on $this->playerDetails['name'] and then removing the break
So the working code looks like this
for ($i = 0; $i < count($this->playerDetails['name']); $i++) {
for ($x=0; $x < count($warArr['participants']) ; $x++){
if($this->playerDetails['name'][$i] == $warArr['participants'][$x]['name']){
$this->playerDetails['warFinalBattleWin'][$i] = $warArr['participants'][$x]['wins'];
}
}
}
Related
Why is this still returning a count of 3 ?
$arr =
[
[
'slug' => 'products-services-pricing',
'text' => 'Products/Services and Pricing',
],
[
'slug' => 'promotions-plan',
'text' => 'Promotions Plan',
],
(1 == 2) ?
[
'slug' => 'distribution-plan',
'text' => 'Distribution Plan',
] : null,
];
echo "Count = ".count($arr)."\n";
print_r($arr);
My foreach is getting messed up. PHP 8.0
I cannot do condition check in foreach because I am using count.
Sure, a null valued element is still considered a valid array element!
For example:
<?php
$arr = [null, null, null];
echo 'Count: ' . count($arr); //Will print 3
In your code, the value of the third element is null, there is no problem with that, no mistery. You are not removing the element, but assigning it a value: null.
Here you got an idea: iterate over the array and remove elements valued null:
$aux = [];
foreach ($arr as $item) {
if (!is_null($item)) {
$aux[] = $item;
}
}
$arr = $aux; //Now $arr has no null elements
Or simply iterate to count not null elements.
$c = 0;
foreach ($arr as $item) {
if (!is_null($item)) {
$c++;
}
}
echo 'Count: ' . $c; //Count without null elements
Or you can build your array adding or not the conditional element. This can be the better solution:
$arr =
[
[
'slug' => 'products-services-pricing',
'text' => 'Products/Services and Pricing',
],
[
'slug' => 'promotions-plan',
'text' => 'Promotions Plan',
],
];
if (1 == 2) {
$arr[] = [
'slug' => 'distribution-plan',
'text' => 'Distribution Plan',
];
}
echo 'Count: ' . count($arr); //Will print 2
If you change the values returned by your ternary and use the spread operator, you'll be able to achieve what you want without any subsequent filtering or fooling around.
Code: (Demo)
...(1 == 2)
? [['slug' => 'distribution-plan', 'text' => 'Distribution Plan']]
: [],
By adding a level of depth to the true branch value, the spread operator will push the single row into the array.
By changing null to an empty array, the spread operator will push nothing into the array.
Kind of, sort of, related:
PHP is there a way to add elements calling a function from inside of array
When I try to push an array of records to my Laravel Collection, I end up with only the first record being inserted into the collection. It was working well before I made a few changes (related to $limit and $test) but now produces this bug.
public static function processOldOrders(int $limit = 1, bool $test = true)
{
//Read CSV and turn into a collection
$allOldOrders = Excel::toArray([], 'orders.csv');
$orderCollection = collect();
$count = 0;
foreach ($allOldOrders as $key => $oldOrder) {
$orderCollection->push(
(object) [
'order_id' => ltrim($oldOrder[$key][0], "#"),
'order_created' => $oldOrder[$key][4],
'email' => $test ? 'test#test.com' : trim(strtolower($oldOrder[$key][5])),
'phone' => ltrim($oldOrder[$key][12], "'"),
'first_name' => $oldOrder[$key][7],
'last_name' => $oldOrder[$key][8],
'purchase_status' => 'a_purchase',
'total_price' => $oldOrder[$key][33],
'items' => [],
'gift_cards' => [],
'coupons' => [],
'shipping_data' => [],
]
);
$count++;
if ($count >= $limit) {
break;
}
}
dd($orderCollection);
In your processOldOrders method by default you set limit = 1. And on the bottom,
$count = 0;
foreach ($allOldOrders as $key => $oldOrder) {
...
$count++;
if ($count >= $limit) {
break;
}
...
there you check it with count. At first time $count is equal to 0, and you plus it 1. Then you checking it with $limit. By default limit is 1 . So it works only one time. Yu have to more than one limit where you call processOldOrders method
There's nothing wrong with your code. But you forgot the output of Excel::toArray(), that it has sub-arrays.
array:1 [
0 => array [ // <-- init
0 => array [ // <-- CSV data
...
So, you can change your $allOldOrders to $allOldOrders[0] :
foreach ($allOldOrders[0] as $key => $oldOrder) {
...
}
I have a already defined array, containing values just like the one below:
$arr = ['a','b','c'];
How could one add the following using PHP?
$arr = [
'a' => 10,
'b' => 5,
'c' => 21
]
I have tried:
$arr['a'] = 10 but it throws the error: Undefined index: a
I am surely that I do a stupid mistake.. could someone open my eyes?
Full code below:
$finishes = []; //define array to hold finish types
foreach ($projectstages as $stage) {
if ($stage->finish_type) {
if(!in_array($stage->finish_type, $finishes)){
array_push($finishes, $stage->finish_type);
}
}
}
foreach ($projectunits as $unit) {
$data[$i] = [
'id' => $unit->id,
'project_name' => $unit->project_name,
'block_title' => $unit->block_title,
'unit' => $unit->unit,
'core' => $unit->core,
'floor' => $unit->floor,
'unit_type' => $unit->unit_type,
'tenure_type' => $unit->tenure_type,
'floors' => $unit->unit_floors,
'weelchair' => $unit->weelchair,
'dual_aspect' => $unit->dual_aspect
];
$st = array();
$bs = '';
foreach ($projectstages as $stage) {
$projectmeasure = ProjectMeasure::select('measure')
->where('project_id',$this->projectId)
->where('build_stage_id', $stage->id)
->where('unit_id', $unit->id)
->where('block_id', $unit->block_id)
->where('build_stage_type_id', $stage->build_stage_type_id)
->first();
$st += [
'BST-'.$stage->build_stage_type_id => ($projectmeasure ? $projectmeasure->measure : '0')
];
if (($stage->is_square_meter == 0) && ($stage->is_draft == 0)) {
$height = ($stage->height_override == 0 ? $unit->gross_floor_height : $stage->height_override); //08.14.20: override default height if build stage type has it's own custom height
$st += [
'BST-sqm-'.$stage->build_stage_type_id => ($projectmeasure ? $projectmeasure->measure * $height: '0')
];
if ($stage->finish_type) {
$finishes[$stage->finish_type] += ($projectmeasure ? $projectmeasure->measure * $height: '0') * ($stage->both_side ? 2 : 1); //error is thrown at this line
}
} else {
if ($stage->finish_type) {
$finishes[$stage->finish_type] += ($projectmeasure ? $projectmeasure->measure : '0');
}
}
}
$data[$i] = array_merge($data[$i], $st);
$data[$i] = array_merge($data[$i], $finishes[$stage->finish_type]);
$i++;
}
The above code is used as is and the array $finishes is the one from the first example, called $arr
You're using += in your real code instead of =. That tries to do maths to add to an existing value, whereas = can just assign a new index with that value if it doesn't exist.
+= can't do maths to add a number to nothing. You need to check first if the index exists yet. If it doesn't exist, then assign it with an initial value. If it already exists with a value, then you can add the new value to the existing value.
If you want to convert the array of strings to a collection of keys (elements) and values (integers), you can try the following:
$arr = ['a','b','c'];
$newVals = [10, 5, 21];
function convertArr($arr, $newVals){
if(count($arr) == count($newVals)){
$len = count($arr);
for($i = 0; $i < $len; $i++){
$temp = $arr[$i];
$arr[$temp] = $newVals[$i];
unset($arr[$i]);
}
}
return $arr;
}
print_r(convertArr($arr, $newVals));
Output:
Array ( [a] => 10 [b] => 5 [c] => 21 )
I created multiple dimensional array and tried to update count value for certain condition as below but not working.
$test[] = [
'firstNm' => 'luke'
,'lastNm' => 'Lee'
,'count' => 10
];
$test[] = [
'firstNm' => 'John'
,'lastNm' => 'Doe'
,'count' => 20
];
foreach ($test as $test01)
{
if ($test01['firstNm'] === 'John'){
$test01['count'] += 70 ;}
}
Looking forward to your help.
Thank you.
Actually you are increasing the value but missing to reasign to the same array. Try this one.
$test[] = [
'firstNm' => 'luke'
,'lastNm' => 'Lee'
,'count' => 10
];
$test[] = [
'firstNm' => 'John'
,'lastNm' => 'Doe'
,'count' => 20
];
foreach ($test as $key => $test01)
{
if ($test01['firstNm'] === 'John'){
$test[$key]['count'] += 70 ;
}
}
print_r($test);
Borrowing from this answer, which cites the PHP manual page for foreach:
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference.1
So you could iterate over the array elements by-reference:
foreach ($test as &$test01)
{
if ($test01['firstNm'] === 'John'){
$test01['count'] += 70 ;
}
}
See this illustrated on Teh Playground.
Otherwise you can iterate using the key=>value syntax:
foreach ($test as $index=>$test01)
{
if ($test01['firstNm'] === 'John'){
$test[$index]['count'] += 70 ;
}
}
I have an array which looks pretty much like this:
$array = [
0 => [
'b' => [
'classname1' => 'data1',
'classname2' => 'data2' // This one must go away
],
'classname3' => 'data3',
1 => [ ... ]
],
'a' => [ ... ],
'classnameN' => 'dataN'
];
This array can have any keys (numeric or string) and can be any levels deep. The question is how to unset part of it by having an array, which values are leading to some data in the first array?
For example using $definer = [0,'b','classname2']; we must delete commented part of an array.
I have a solution on how to find, what I need to delete, but I've realised, that I don't know how to travel back and assign new value to initial array:
$array_traveler = $array;
for($i = 0; $i < count($definer) - 1; $i++) {
$array_traveler = $array_traveler[$definer[$i]];
}
unset($array_traveler[$definer[count($definer) - 1]]);
Use "pointer"
$array_traveler = &$array;
for($i = 0; $i < count($definer) - 1; $i++) {
$array_traveler = &$array_traveler[$definer[$i]];
}
unset($array_traveler[$definer[count($definer) - 1]]);