I want to separate numbers, like a serial number, ex:
I've got 1-1000,
if I want to remove 1-100, then I will get 101-1000
if I want to remove 901-1000, then I will get 1-900
if I want to remove 101-200 then I will get 1-100 and 201-1000
and so on.
I just insert first number and last number, like 1 and 100.
The problem is, I am using MySQL to store data, this is my tables:
[items(id,name), serials(id,name), details(id,item_id,serial_id,first,last)][1]
I've a solution, but I think my solution is too long and isn't efficient for my code if I work with large data, this is my solution
public function checkSerialNum(array $data){
$item_id = $data['item_id'];
$serial_id = $data['serial_id'];
$first = $data['first'];
$last = $data['last'];
if($first > $last) return false;
$sql = "SELECT * FROM details WHERE item_id = '$item_id' AND serial_id = '$serial_id'";
$details = $this->db->run($sql)->fetchAll();
$new_detail = [];
foreach($details as $key => $detail){
if($first == $detail->first && $last == $detail->last){ // 1 - 1000 -> 0 - 0
$new_detail['item_id'][] = $item_id;
$new_detail['serial_id'][] = $serial_id;
$new_detail['first'][] = 0;
$new_detail['last'][] = 0;
$new_detail['old_id'][] = $detail->id;
}elseif($first > $detail->first && $last == $detail->last){ // 901-1000 -> 1 - 900
$new_detail['item_id'][] = $item_id;
$new_detail['serial_id'][] = $serial_id;
$new_detail['first'][] = $detail->first;
$new_detail['last'][] = $first - 1;
$new_detail['old_id'][] = $detail->id;
}elseif($first == $detail->first && $last < $detail->last){ // 1 - 100 -> 101 - 1000
$new_detail['item_id'][] = $item_id;
$new_detail['serial_id'][] = $serial_id;
$new_detail['first'][] = $last + 1;
$new_detail['last'][] = $detail->last;
$new_detail['old_id'][] = $detail->id;
}elseif($first > $detail->first && $last < $detail->last){ //101-200 -> 1-100 & 201-1000
$new_detail['item_id'][] = $item_id;
$new_detail['serial_id'][] = $serial_id;
$new_detail['first'][] = $detail->first;
$new_detail['last'][] = $first - 1;
$new_detail['old_id'][] = $detail->id;
$new_detail['item_id'][] = $item_id;
$new_detail['serial_id'][] = $serial_id;
$new_detail['first'][] = $last + 1;
$new_detail['last'][] = $detail->last;
}
}
return $this->tidyArray($new_detail);
}
public function tidyArray($arr){
$new_arr = [];
foreach($arr as $k => $array){
for($i=0;$i < count($array); $i++){
$new_arr[$i][$k] = $array[$i];
}
}
return $new_arr;
}
public function removeSerialNum(array $data){ //
$new_details = $this->checkSerialNum($data);
if(!$new_details) return false;
$item_id = $data['item_id'];
$serial_id = $data['serial_id'];
foreach($new_details as $nd){
if(isset($nd['old_id'])){
$old_id = $nd['old_id'];
$sql = "DELETE FROM details WHERE item_id = '$item_id' AND serial_id = '$serial_id' AND id = '$old_id'";
$this->db->run($sql);
unset($nd['old_id']);
}
$this->insertData('details',$nd);
}
return true;
}
}
The $data is returning something like this
$data = [
'first' => 1,
'last' => 100,
'item_id' => 1,
'serial_id' => 1
];
The function tidyArray() is changing the format array from something like this:
////// it will return like this if I'm not breaking any range, like I've 821-900 and I just input 821-850
Array
(
[item_id] => Array
(
[0] => 1
)
[serial_id] => Array
(
[0] => 1
)
[first] => Array
(
[0] => 821
)
[last] => Array
(
[0] => 850
)
[old_id] => Array
(
[0] => 8
)
)
/////but if I've 821-900 and input like 851-860, it will return like this
Array
(
[item_id] => Array
(
[0] => 1
[1] => 1
)
[serial_id] => Array
(
[0] => 1
[1] => 1
)
[first] => Array
(
[0] => 821
[1] => 861
)
[last] => Array
(
[0] => 850
[1] => 900
)
[old_id] => Array
(
[0] => 10
)
)
to something like this:
//////it will return like this if I'm not breaking any range, like I've 821-900 and I just input 821-850
Array
(
[0] => Array
(
[item_id] => 1
[serial_id] => 1
[first] => 811
[last] => 900
[old_id] => 8
)
)
/////but if I've 821-900 and input like 851-860, it will return like this, its like new range of data, I will explain old_id below..
Array
(
[0] => Array
(
[item_id] => 1
[serial_id] => 1
[first] => 821
[last] => 850
[old_id] => 10
)
[1] => Array
(
[item_id] => 1
[serial_id] => 1
[first] => 861
[last] => 900
)
)
and the last is function removeSerialNum() this will delete the affected range of number, example I've 101-200, 301-900 in my database, then I want to remove 151-160, so it will select using the affected row and that's 101-200 row then delete it and change with a new one, this is my data from the array above, this will explain what old_id use for:
"id" "item_id" "serial_id" "first" "last"
"3" "1" "1" "101" "150"
"4" "1" "1" "161" "200"
"5" "1" "1" "301" "350"
"7" "1" "1" "701" "800"
"9" "1" "1" "802" "810"
"10" "1" "1" "821" "900" ->the affected row
in case you wonder what is function insertData() looks like:
public function insertData($table,array $data){
$sql = "INSERT INTO $table SET ";
$vals = [];
foreach($data as $key => $val){
$vals[] = "$key = '$val'";
}
$sql .= implode(',',$vals);
return $this->db->run($sql);
}
This solution is working for me and I just want to ask how can I get a same result but with less lines of code or in a smarter way.
Related
I have an array like that:
[0] => Array
(
[sendby] => 3
[refresh] => 0
[last] => 0
)
[1] => Array
(
[sendby] => 3
[refresh] => 1
[last] => 1
)
[2] => Array
(
[sendby] => 8
[refresh] => 1
[last] => 1
)
I want the value last to be 1 when the value sendby (here 3 and 8) is the last of the entire array! How can I do that?
Get the last 2 value and compare with array [3,8]
// get array of sendby values
$temp = array_column($array, 'sendby');
// get array with two last values
$temp = array_slice($temp, -2);
// Check
if ($temp == [3,8]) {
$value = 1;
}
else {
$value = 0;
}
or in one line
$value = array_slice(array_column($array, 'sendby'), -2) == [3,8] ? 1 : 0;
demo
Update on base of comments
// get array with two last values
$temp = array_slice(array_column($array, 'sendby'), -2);
foreach($array as &$x) {
// If current send by is in $temp array
if(in_array($x['sendby'], $temp)) {
$x['last'] = 1;
}
else {
$x['last'] = 0;
}
}
print_r($array);
You can use an array to assist the existing ocurrences of that id. I have an working example (Tested on php sandbox):
$array = array(
0 => array
(
'sendby' => 3,
'refresh' => 0,
),
1 => array
(
'sendby' => 3,
'refresh' => 1,
),
2 => array
(
'sendby' => 8,
'refresh' => 1,
)
);
$ocurrences = [];
foreach($array as $key => $elem ){
$id = $elem['sendby'];
if (isset($ocurrences[$id])) {
$array[$ocurrences[$id]]['last'] = 0;
$array[$key]['last'] = 1;
$ocurrences[$id] = $key;
} else {
$ocurrences[$id] = $key;
$array[$key]['last'] = 1;
}
}
echo print_r($array, 1);
The result:
Array
(
[0] => Array
(
[sendby] => 3
[refresh] => 0
[last] => 0
)
[1] => Array
(
[sendby] => 3
[refresh] => 1
[last] => 1
)
[2] => Array
(
[sendby] => 8
[refresh] => 1
[last] => 1
)
)
Basically I used an array with the ocurrences of the 'sendby' index of the array. The $occurences array has the elements with the key of the last checked element.
Lets suppose your array is $array;
You could iterate through it and if it's the last element, then set [last] to 1, else set to 0;
Try to run the below code after your array is populated.
$i =1;
foreach($array as $ar) {
$ar->last = ($i == count($array) && ($ar->sendby == 3 || $ar->sendby == 8)) ? 1 : 0;
$i++;
}
$count = count($arr) ;
$i = 0;
foreach($arr as $key=>$val) {
if(++$I === $count) {
echo "last element" ;
}
}
This question already has answers here:
Group array data on one column and sum data from another column
(5 answers)
Closed 9 months ago.
I have the following array
Array (
[0] => Array
(
[0] => ALFA
[1] => 213
)
[1] => Array
(
[0] => ALFA
[1] => 151
)
[2] => Array
(
[0] => ALFA
[1] => 197
)
[3] => Array
(
[0] => BETA
[1] => 167
)
[4] => Array
(
[0] => ZETA
[1] => 254
)
[5] => Array
(
[0] => GAMA
[1] => 138
)
[6] => Array
(
[0] => GAMA
[1] => 213
)
)
And I would like to group the key[0] of the subarray so I can see how many equal keys it has.
Something like that:
ALFA => 3
BETA => 1
EPSI => 1
GAMA => 2
I tried with array_count_values, but without success.
foreach ($array as $value) {
echo '<pre>';
print_r(array_count_values($value));
echo '</pre>';
}
With that we have following result:
Array
(
[ALFA] => 1
[213] => 1
)
Array
(
[ALFA] => 1
[151] => 1
)
...
Array
(
[GAMA] => 1
[213] => 1
)
And after that I would like to sum the values of each group as well.
ALFA => 213 + 151 + 197
BETA => 167
ZETA => 254
GAMA => 138 + 213
I think that when we solve the first part of the problem, the second would follow easier with quite the same method.
The final purpose is to divide the sum of values by the number of occurrences of each key group, so we can have an average of the values just like that:
ALFA => (213+151+197) / 3 = 187
BETA => 167
ZETA => 254
GAMA => (138+213) / 2 = 175,5
This is not the main problem, but as I said, I'm stuck with the beginning of the solution and would appreciate any help.
I'm surprised at all the long and complicated answers. However, the initial foreach to model your data to something manageable is needed. After that you just need to do a really simple array_walk.
<?php
$result = array();
foreach ($array as $el) {
if (!array_key_exists($el[0], $result)) {
$result[$el[0]] = array();
}
$result[$el[0]][] = $el[1];
}
array_walk($result, create_function('&$v,$k', '$v = array_sum($v) / count($v);'));
?>
Result:
Array
(
[ALFA] => 187
[BETA] => 167
[ZETA] => 254
[GAMA] => 175.5
)
Solution for you is here:
Code:
$input = [
['alfa', 123],
['alfa', 223],
['alfa', 122],
['alfa', 554],
['alfa', 34],
['dalfa', 123],
['halfa', 223],
['dalfa', 122],
['halfa', 554],
['ralfa', 34]
];
$result = [];
foreach ($input as $node) {
if (isset($result[$node[0]])) {
$result[$node[0]] = ['sum' => $result[$node[0]]['sum'] + $node[1], 'count' => $result[$node[0]]['count'] + 1];
} else {
$result[$node[0]] = ['sum' => $node[1], 'count' => 1];
}
}
print_r($result);
foreach ($result as $key => &$data) {
$data = $data['sum'] / $data['count'];
}
print_r($result);
Output:
Array
(
[alfa] => Array
(
[sum] => 1056
[count] => 5
)
[dalfa] => Array
(
[sum] => 245
[count] => 2
)
[halfa] => Array
(
[sum] => 777
[count] => 2
)
[ralfa] => Array
(
[sum] => 34
[count] => 1
)
)
Array
(
[alfa] => 211.2
[dalfa] => 122.5
[halfa] => 388.5
[ralfa] => 34
)
$sort = array();
foreach ($array as $value) {
$sort[$value[0]][] = $value[1];
}
then you count how many keys each has
$keys = array();
foreach($sort as $k => $v) {
$keys[$k] = count($v);
}
then for calculating the amount
$sum = array();
$average = array();
foreach($sort as $k => $v) {
$amount = 0;
foreach($v as $val) {
$amount += $val;
}
$sum[$k] = $amount;
$average[$k] = $amount / $keys[$k];
}
HOWEVER, If you want all the details in one array:
$final = array();
foreach ($array as $value) {
$final[$value[0]]["values"][] = $value[1];
}
foreach($final as $k => $v) {
$final[$k]["amount"] = count($v['values']);
$amount = 0;
foreach($v['values'] as $val) {
$amount += $val;
}
$final[$k]["sum"] = $amount;
$final[$k]["average"] = $amount / $final[$k]["amount"];
}
example: http://jdl-enterprises.co.uk/sof/25789697.php
Includes Output
Just copy the codes to your favorite text editor, sure it works perfectly.
$items = [
['ALFA',213],
['ALFA',151],
['ALFA',197],
['BETA',167],
['ZETA',254],
['GAMA',138],
['GAMA',213]
];
echo '<pre>' . print_r($items,true) . '</pre>';
$result;
foreach ($items as $value) {
# code...
if (isset($result[$value[0]])) {
$sum = $result[$value[0]]['sum'] + $value[1];
$count = $result[$value[0]]['count'] + 1;
$result[$value[0]] = ['sum' => $sum , 'count' => $count, 'divided' => ($sum / $count)];
} else {
$result[$value[0]] = ['sum' => $value[1] , 'count' => 1 , 'divided' => ($value[1] / 1) ];
}
}
echo '<pre>' . print_r($result,true) . '</pre>';
$myArray = [
["ALFA",213],
["ALFA",151],
["ALFA",197],
["BETA",167],
["ZETA",254],
["GAMA",138],
["GAMA",213]
];
$a1 = array(); //TEMPORARY ARRAY FOR KEEPING COUNT & TOTAL VALUES
$res = array(); //ARRAY USED TO KEEP RESULT
foreach($myArray as $val)
{
//AVOID PESKY NOTICES FOR UNDEFINED INDEXES
if ( !array_key_exists($val[0],$a1) ) {
$a1[$val[0]] = array("count" => 0,"total" => 0);
$res[$val[0]] = 0;
}
//INCREMENT THE COUNT OF INSTANCES OF THIS KEY
$a1[$val[0]]["count"]++;
//INCREMENT THE TOTAL VALUE OF INSTANCES OF THIS KEY
$a1[$val[0]]["total"]+=$val[1];
// UPDATE RESULT ARRAY
$res[$val[0]] = $a1[$val[0]]["total"] / $a1[$val[0]]["count"];
}
print_r($res);
Should result in:
Array
(
[ALFA] => 187
[BETA] => 167
[ZETA] => 254
[GAMA] => 175.5
)
Sample: http://phpfiddle.org/lite/code/a7nt-5svf
I've a series of arrays with values that goes from 1 to 5. Almost every array has missing values, some even dont have any values. My objective is to fill the missing values with 0. All those arrays are stored into a multidimensional array.
My array looks like:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
[2] => Array
(
[0] => 1
[1] => 5
)
[3] => Array
(
[0] => (this array has no values)
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
etc...
)
How it should be:
Array
(
[1] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 0
[4] => 0
)
[2] => Array
(
[0] => 1
[1] => 0
[2] => 0
[3] => 0
[4] => 5
)
[3] => Array
(
[0] => 0
[1] => 0
[2] => 0
[3] => 0
[4] => 0
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
)
etc...
)
Any help would be appriciated!
For each of your subarrays loop through the numbers 1 to 5, and if that value exists set its key to be one less than its value:
$newarray = array();
foreach($arr as $key => $subarr) {
for ($i = 1; $i <= 5; $i++) {
if (in_array($i, $subarr)) $newarray[$key][$i - 1] = $i;
else $newarray[$key][$i - 1] = 0;
}
}
Where $newarray is your output and $arr is your input array.
You may want to note that PHP does not truly do multidimensional arrays. It only allows you to relate 2 flat arrays together which is not true multidimensionality.
This does not work and will produce results described above.
$menu[1] = "My Training"; //not $menu[1][0]
$menu[1][1] = "To Do List";
$menu[1][2] = "Catalog";
$menu[1][3] = "Self-Report";
$menu[1][4] = "Completions";
$menu[2] = "Manager";
$menu[2][1] = "Direct Reports";
$menu[2][2] = "Incompletes";
$menu[2][3] = "Completions";
$menu[3] = "Instructor";
$menu[3][1] = "My Classes";
$menu[3][2] = "Printables";
$menu[3][3] = "Qualifications";
This does work.
$menu[1] = "My Training"; //not $menu[1][0]
$submenu[1][1] = "To Do List";
$submenu[1][2] = "Catalog";
$submenu[1][3] = "Self-Report";
$submenu[1][4] = "Completions";
$menu[2] = "Manager";
$submenu[2][1] = "Direct Reports";
$submenu[2][2] = "Incompletes";
$submenu[2][3] = "Completions";
$menu[3] = "Instructor";
$submenu[3][1] = "My Classes";
$submenu[3][2] = "Printables";
$submenu[3][3] = "Qualifications";
$submenu is only related to $menu through the first key number as there are no first dimension values to $submenu.
Something like this (array_pad() won't do the trick). $myArray is your source array. Completed array is returned in $result:
$result = array();
foreach( $myArray as $subKey=>$subArray ) {
for( $i=0; $i<5; $i++ ) {
if( isset( $subArray[$i] )) {
$result[$subKey][$i] = $subArray[$i];
} else {
$result[$subKey][$i] = 0;
}
}
}
Note, we do copy of the array. You cannot fill array in-place.
It's been many years since I wrote any PHP but something like this might do the trick I guess?
for($i = 0; $i < 5; $i++)
{
if(empty($myArray[$i])
{
$myArray[$i] = 0;
}
}
I am using:
$input = array("1", "2", "3", "4", "5");
Now I want to start by printing the first value from the array (1) and another value for the remaining ones (2,3,4,5). Then next time, the print value will be 2 and further values (3,4,5,1). And so on, until the print value is 5 and the other values will be (1,2,3,4).
I am using a for-loop, but after the value 5, the loop should break...
What to do for this case....
out put should be: 1 the first time, then 2 then 3 then 4 then 5 then again 1 then continue on every refresh
Does this do what you are looking for?
<?php
$input = array("1", "2", "3", "4", "5");
$arr = array();
foreach ($input as $item) {
$i = array_shift($input);
$arr[] = $input;
$input[] = $i;
}
print_r($arr);
OUTPUT
Array
(
[0] => Array
(
[0] => 2
[1] => 3
[2] => 4
[3] => 5
)
[1] => Array
(
[0] => 3
[1] => 4
[2] => 5
[3] => 1
)
[2] => Array
(
[0] => 4
[1] => 5
[2] => 1
[3] => 2
)
[3] => Array
(
[0] => 5
[1] => 1
[2] => 2
[3] => 3
)
[4] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
)
You want this:
<?php
session_start();
if(!isset($_SESSION['loop_num'])){
$_SESSION['loop_num'] = 1;
}
$loop = true;
echo "Current: {$_SESSION['loop_num']} <br>";
$i = $_SESSION['loop_num'];
while($loop === true) {
if($i >= 5){
$i = 1;
} else {
$i++;
}
if($_SESSION['loop_num'] == $i){
$loop = false;
break;
}
$others[] = $i;
}
if($_SESSION['loop_num'] >= 5){
$_SESSION['loop_num'] = 1;
} else {
$_SESSION['loop_num']++;
}
print_r($others);
?>
Output:
Current: 4
Array ( [0] => 5 [1] => 1 [2] => 2 [3] => 3 )
Current: 5
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
etc..
try implementing this solution:
$size = count($input);
$input = array_merge($input,$input);
for($i=0;$i<$size;$i++){
$output = array_slice($input,$i,$size-1);
print_r($output);
}
If you just want a constantly rotating array that loops forever, this works:
$array = range(1,5);
foreach($array as &$number) {
echo $number . PHP_EOL;
array_push($array, array_shift($array));
}
If you want it to rotate per page load, setting the front number to one variable the rest in line in a dedicated array, this works:
session_start();
if(!$_SESSION['loop_array']) {
$_SESSION['loop_array'] = range(1,5);
}
$current_value = array_shift($_SESSION['loop_array']);
$others_values = $_SESSION['loop_array'];
// Push current value to back of rotation, leaving next in line for
// next page load.
array_push($current_value, $_SESSION['loop_array']);
This will also work with the following arrays (or any array):
$_SESSION['cute'] = array("dog", "cat", "pony", "bunny", "moose");
$_SESSION['ordinals'] = array("first", "second", "third", "fourth", "fifth");
$_SESSION['tick_tock_clock'] = array("I", "II", "III", "IV", "V", "VI",
"VII", "VIII", "IX", "X", "XI", "XII");
$_SESSION['randomness'] = array('butter', 'pillow', 'Alabama', 'bleeding gums');
<?php
$input = array("1", "2", "3", "4", "5");
while(!empty($input)) {
foreach($input as $i) {
var_dump($i);
}
$input = array_splice($input, 0, count($input) - 1);
}
?>
How to count the item-qty and current code :-
$q = $_POST['item-qty'];
$i = count($q);
$k = 0;
while ($k < $i) {
$select = 'SELECT * FROM location';
$query = $db->rq($select);
$price = $db->fetch($query);
if ($_POST['item-qty'][$k] < 3) {
$get = $price['normal_price'];
$price = $get * $_POST['item-qty'][$k];
$_SESSION['order'][$_POST['item-id'][$k]] = array(
"item-id" => $_POST['item-id'][$k],
"item-qty" => $_POST['item-qty'][$k],
"item-name" => $_POST['item-name'][$k],
"item-price" => $price,
);
} else {
$get = $price['member_price'];
$price = $get * $_POST['item-qty'][$k];
$_SESSION['order'][$_POST['item-id'][$k]] = array(
"item-id" => $_POST['item-id'][$k],
"item-qty" => $_POST['item-qty'][$k],
"item-name" => $_POST['item-name'][$k],
"item-price" => $price,
);
}
}
here the array output
Array
(
[order] => Array
(
[1] => Array
(
[item-id] => 1
[item-qty] => 1
[item-name] => Adidas
[item-price] => 100
)
[2] => Array
(
[item-id] => 2
[item-qty] => 1
[item-name] => Nike
[item-price] => 150
)
)
)
Question :
How to implement other code if item-qty (in all array) is greater than or equal to 3 will use $price['member_price']
let me know :)
I'm guessing you meant the total item-qty of everything?
$qty_sum = 0
foreach($_SESSION['order'] as $order){
$qty_sum += $order['item-qty'];
}