If the array has more then 10 elements ... then what? - php

I have a top 10 list right here. The list contains all the IPs who visited the domain (out of my log files) and my code below gives me the top 10 IPs of them.
But I want it more dynamically. Like if there are more then 10 different IPs, give me just the 10 IPs that appear the most. If the amount of different IPs is less then 10, just give me all the IPs there are.
The code for this:
$all_ips = array_count_values($ip_array);
arsort($all_ips);
$count = count($all_ips);
$keys = array_keys($all_ips);
$topTenIp = array();
$count = $count -1;
for($i=0; $i <= $count; $i++){
if($count < 9){
$topTenIp[] = $keys[$i];
}else{
$topTenIp[] = $keys[$i];
}
}
This works okay but not perfect. If the amount of IPs is below 10, it gives me all the IPs there are. But if there are more then 10, it doesn't give me the 10 most appearing IPs, it just gives me all IPs of the log script.
I hope you understood what I was trying to say. I'm from Germany, so my English isn't that good.
Thanks anyway :)

I don't really see how this is related to Laravel at all, but anyway:
$counted = array_count_values($ipArray);
arsort($counted);
$top = array_keys(array_slice($counted, 0, 10));
Would be a faster, simpler way to get top 10 items, given that your source $ipArray is a simple array of IP addresses.

What you're doing isn't logical. Say $all_ips is 30 then every 30 iterations will execute in the else. Resulting in a array of 30 ip's.
You'll need to change your if and else part.
for($i=0; $i <= $count; $i++){
if($i < 9){
$topTenIp[] = $keys[$i];
} else {
break; //Break out of the loop
}
}

This is because you are doing same code in if and else condition.
You can do like this:
for($i=0; $i <= $count; $i++){
if($i < 9){
$topTenIp[] = $keys[$i];
}
}

please try the following
$all_ips = array_count_values($ip_array);
arsort($all_ips);
$count = count($all_ips);
$keys = array_keys($all_ips);
$topTenIp = array();
$count = $count -1;
for($i=0; $i <= $count; $i++){
if($count < 9){
$topTenIp[] = $keys[$i];
}else{
$topTenIp[] = $keys[$i];
}
if( $i >= 9 )
{
break;
}
}
in your code there is no check given if number count is grater than 10 , so please give a check , i have updated my answer

Related

Exam Qn: Convert do while loop to for loop (PHP)

Recently, my exams got over. My last exam was based on PHP. I got the following question for my exam:
"Convert the following script using for loop without affecting the output:-"
<?php
//Convert into for loop
$x = 0;
$count = 10;
do
{
echo ($count. "<BR>");
$count = $count - 2;
$x = $x + $count;
}
while($count < 1)
echo ($x);
?>
Please help me as my computer sir is out of station and I am really puzzled by it.
Well, If I understand well, You have to use "for" loop, instead of "do...while", but the printed text must not change.
Try:
$count = 10;
$x = 0;
$firstRun = true;
for(; $count > 1 || $firstRun;) {
$firstRun = false;
echo ($count . "<BR>");
$count -= 2;
$x = $x + $count;
}
echo ($x);
By the way loop is unnecessary, because $count will be greater than 1 after the first loop, so the while will get false.
EDIT
$firstRun to avoid infiniteLoop
$count in loop
EDIT
Fixed code for new requirement
Removed unnecessary code
Hmmm I don't know if your teacher wanted to own you... but the do{} will execute only once since $count is never < 1.
The output of your teacher's code is:
10
8
I presume there was a mistake in the code and the while would be while($count > 1) which would make more sense (since it's weird to ask for a loop to output only 10 8) and would result in this output:
10
8
6
4
2
20
Then a good for() loop would have been :
$x = 0;
$count = 10;
for($i = $count; $i > 1; $i -= 2)
{
$count -= 2;
echo $i . "<br>";
$x += $count;
}
echo $x;
Which will output the same values.
If you can, ask your teacher for this, and comment the answer ^^ ahahah

combinations without duplicates using php

I need all possible combinations in math sense (without duplicates) where n=30 and k=18
function subcombi($arr, $arr_size, $count)
{
$combi_arr = array();
if ($count > 1) {
for ($i = $count - 1; $i < $arr_size; $i=$i+1) {
$highest_index_elem_arr = array($i => $arr[$i]);
foreach (subcombi($arr, $i, $count - 1) as $subcombi_arr)
{
$combi_arr[] = $subcombi_arr + $highest_index_elem_arr;
}
}
} else {
for ($i = $count - 1; $i < $arr_size; $i=$i+1) {
$combi_arr[] = array($i => $arr[$i]);
}
}
return $combi_arr;
}
function combinations($arr, $count)
{
if ( !(0 <= $count && $count <= count($arr))) {
return false;
}
return $count ? subcombi($arr, count($arr), $count) : array();
}
$numeri="01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30";
$numeri_ar=explode(".",$numeri);
$numeri_ar=array_unique($numeri_ar);
for ($combx = 2; $combx < 19; $combx++)
{
$combi_arr = combinations($numeri_ar, $combx);
}
print_r($combi_arr);
It works but it terminates with an out of memory error, of course, number of combinations is too large.
Now I do not need exactly all the combinations. I need only a few of them.
I'll explain.
I need this work for a statistical study over Italian lotto.
I have the lotto archive in this format saved in $archivio array
...
35.88.86.03.54
70.72.45.18.09
55.49.35.30.43
15.52.49.41.72
74.26.54.77.90
33.14.56.42.11
08.79.41.01.52
82.33.32.83.43
...
A full archive is available here
https://pastebin.com/tut6kFXf
newer extractions are on top.
I tried (unsuccessfully) to modify the function to do this
for each 18 numbers combination found by the function combinations, the function should check if there are min. 3 numbers in one of the first 30 rows of $archivio. If "yes", the combination must not be saved in combination array, this combination has no statistical value for my need. If "no", the combination must be saved in combination array, this combination has great statistical value for my need.
In this way the total combinations will be no more than some hundred or thousand and I will avoid the out of memory and I'll have what I need.
The script time will be surely long but there should not be out of memory using the way above.
Anyone is able to help me in this ?
Thank you

PHP infinity loop [While]

I am having some problems with PHP.
I used while to sum a number's digits always that it has more than two digits, some how, it gets into an infinity loop.
e.g: 56 = 5 + 6 = 11 = 1+1= 2.
Here is the code:
$somaP = 0;
$numPer = (string)$numPer; //$numPer = number calculated previously
while (strlen($numPer) > 1){
for ($j = 0; $j < strlen($numPer); $j++){
$somaP = $somaP + (int)($numPer[$j]);
}
$numPer = (string) $somaP;
}
Can anyone help me? Guess it is a simple mistake, but I couldn't fix it.
You need to reset the value of $somaP in your while loop.
Currently it continues to increase its value every time through the loop.
Try this:
$numPer = (string)$numPer; //$numPer = number calculated previously
while (strlen($numPer) > 1){
$somaP = 0;
for ($j = 0; $j < strlen($numPer); $j++){
$somaP = $somaP + (int)($numPer[$j]);
}
$numPer = (string) $somaP;
}
Take a look at this line:
$numPer = (string) $somaP;
It seems that the length of $somaP is never lesser (or equal) than 1. So the length of $numPer is never lesser (or equal) than 1.
What are you trying to do?
It's unclear to me.
This for example would add every number in a string together?
E.g "1234" = 1+2+3+4 = 10
$total = 0;
for($i = 0; i < strlen($string); $i++){
$total += $string[$i];
}
echo $total;
This looks cleaner I would say:
$numPer = 56;
while ($numPer > 9){
$numPer = array_sum(str_split($numPer));
}
echo $numPer;
PHP handles all string <> number conversions for you, so no need to do (string) on a number unless really needed.

Modulus inside loop

I have an array that I am looping through and breaking up into chunks of 50. However occasionally the number of items inside that array are more than what fits inside that chunk of 50 ex.:
$array = array(); // has 220 rows
for ($i = 0; $i < count($array); $i++) {
$j[] = $i;
if ($i % 50 == 1) {
print_r($j); // do something here with the 50 rows
$j = null;
}
}
The problem here is that this will not print anything after 201. I know there is some algebraic math involved in solving this but I am drawing a blank. Its times like these where I really wish I had paid attention in math class back in high school.
I think array_chunk fits up your requirement and no maths required.
$result_array = array_chunk($array, 50, true);
Add additional condition
if ($i % 50 == 1 || count($array)-1 == $i)
You just have to redeclare the array is my guess:
$array = array(); // has 220 rows
for ($i = 0; $i < count($array); $i++) {
$j[] = $i;
if ($i % 50 == 1) {
print_r($j); // do something here with the 50 rows
$j = array() ;
}
}
Once you perform $j = null there is no way you can do $j[] = $i
$array = array(); // has 220 rows
for ($i = 0; $i < count($array); $i++) {
$j[] = $i;
if ($i % 50 == 1) {
doSomething($j); // do something here with the 50 rows
$j = array(); // reset the array
}
}
doSomething($j); // with the last 20 entries
After your loop is finished, you will have the remaining 201 through 220 entries in $j, so just do your stuff again.
array_chunk
might be useful. Basically splits the array into chunks returning a multi dimensional array

Not sure the loop I need to use every two variables

I have a problem where I have an array $user.
I have $_SESSION['players'] which has the total amount of $user.
I need a function where I can take the user1 and 2 and use them. Then move on to user3 and 4 and use them, and so on.. until I have used all the players. Obviously the total $user[$i] would be players-1.
Anyone have a solution for this?
Thanks
Would this suit your needs? This requires that there be an even number of players to work properly though, unless you stick in a check for odd numbers:
for ($i = 0; $i < $_SESSION['players']; $i += 2) {
$userA = $user[$i];
$userB = $user[$i + 1];
// Do things with $userA and $userB variables...
}
just because you're taught how to use for loops in one way does not mean that you're stuck continuing to use them the way you were taught:
$length = count($users);
$length = $_SESSION['players'];
for ($i = 0; $i < $length; $i += 2)
{
if (!isset($user[$i], $user[$i + 1])) break;
$userOne = $user[$i];
$userTwo = $user[$i+1];
//do stuff
}
I realized that isset wasn't necessary, the for call could be modified more:
$length = $_SESSION['players'];
for ($i = 0; ($i + 1) < $length; $i += 2)
{
$userOne = $user[$i];
$userTwo = $user[$i+1];
//do stuff
}
EDIT to change how the length was calculated:
EDIT to validate that user exists
EDIT to add consolidated version

Categories