Ok, I got a digital book of 30.000 lines. I want to show only the first 20 lines of a chapter as a preview, every chapter got 300 lines.
Anyone an idea how to solve this? I tried the following:
foreach ($lines as $n => $line) {
if ($n >= 0 && $n =< 20) {
echo $line;
}
This will result in showing the first 20 lines of the first chapter. So how do I repeat this for all the other lines?
show 0-20
show 300-320
show 600-620
show 900-920
etc..
Thanks in advance!
You can do it with:
$rgChapters = [];
$rFile = fopen('/path/to/file', 'r');
$iLines = 20;
$iChapter = 300;
$i = 0;
while($sData = fgets($rFile) && !feof($rFile))
{
if($i % $iChapter < $iLines)
{
$rgChapters[floor($i/$iChapter)].=$sData.PHP_EOL;
}
$i++;
}
fclose($rFile);
-as a result, you'll get an array with first 20 lines every 300 lines (or you can directly output data rather than store it in array)
To print chapter 5
$chapter = 5;
$pages = 20;
$start = $chapter*$pages;
for($i=$start, $c=$start+$pages-1; $i < $c; $i++)
{
echo $lines[$i];
}
Just found the answer myself on an earlier SO question:
foreach ($lines as $n => $line) {
if ($n % 300 > 0 && $n % 100 <= 20) {
echo $line; // or whatever
}
}
Based on the answer written by Michael Berkowski (PHP read in every 10 out of 100 lines)
Related
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
I have been asked to solve this question. Please suggest me how to solve this.
$string = "kkjnmnmnjjjnmn";
here I need to find consecutively repeated string of length 3. for example - kkj has occurred only once and jnm 2 times and nmn 3 times.
Starting from first character, going in right side direction, 3 consecutive characters which are repeated more than once should be the output.
Preg_match_all will result as nmn - 2 times and not as 3 times.
How to solve this?
$string = "kkjnmnmnjjjnmn";
$length = strlen($string);
$pieces = [];
for ($i = 0; $i < $length - 2; $i++) {
$piece = substr($string, $i, 3);
if (array_key_exists($piece, $pieces)) {
$pieces[$piece] += 1;
} else {
$pieces[$piece] = 1;
}
}
// $pieces will contain what you need
This one without using any build in functions, Try
$string = "kkjnmnmnjjjnmn";
$i = 0;
$strarr = array();
while(isset($string[$i+2])){
if(!isset($strarr[$string[$i].$string[$i+1].$string[$i+2]]))
$strarr[$string[$i].$string[$i+1].$string[$i+2]] = 1;
else
$strarr[$string[$i].$string[$i+1].$string[$i+2]] += 1;
$i++;
}
print_r($strarr);
Here's my thought.
$arr = array();
for ($i = 0; $i <= strlen($string) - 3; $i++) {
$part = substr($string, $i, 3);
if (array_key_exists($part, $arr)) {
$arr[$part]++;
} else {
$arr[$part] = 1;
}
}
foreach ($arr as $key => $value) {
//output the result
}
well iam not a php expert but after examine the previous answers,i found an alter solution too here it is:
$string='aaaabcdeeeffaaabh';
$arr_str=array();
for($i=0;$i<strlen($string);$i++)
{
if(in_array($string[$i],$arr_str[$char[$i]]))
{
$arr_str[$string[$i]]=1;
}
else
{
$arr_str[$string[$i]]+=1;
}
}
foreach($arr_str as $key => $value)
{
echo $key.' Repeats '.$value.' Times'.'<br/>';
}
OUTPUT:
a Repeats 7 Times
b Repeats 2 Times
c Repeats 1 Times
d Repeats 1 Times
e Repeats 3 Times
f Repeats 2 Times
h Repeats 1 Times
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
Im trying to compare the first 10 lines of 100 lines of $completeGoogle(5000Lines) and count the number of matches with another file. However my count should be between 1-10 and I am getting an answer of 5010???
foreach(new SplFileObject($completeGoogle) as $n => $line)
if($n % 100 < 10)
{
$f_Api = fopen($apiFile,'r');
for ($i = 0 ;$i < 10; $i++)
{
$top10 = fgets($f_Api);
if ($line === $top10);
{
$count++;
}
}
fclose($f_Api);
}
You compare each 1-9, 100-109... line in one file with 10 lines from another and sum all matches in one variable $count.
If everything is equal you must get 500 (lines from first file) * 10 (lines from other) = 5000 matches.
The reason why this was failing my was because of a simple ";" after the if statement.
foreach(new SplFileObject($completeGoogle) as $n => $line)
if($n % 100 < 10)
{
$f_Api = fopen($apiFile,'r');
for ($i = 0 ;$i < 10; $i++)
{
$top10 = fgets($f_Api);
if ($line === $top10)
{
$count++;
}
}
fclose($f_Api);
}
I'm trying to read in a text file of 5000 lines. However I only want to get the first 10 lines of every 100 lines. So line 1-10, line 101 - 110, line 200 - 210 etc. I just cant figure out the logic to use.
$count = count(file($text))
for ($i = 0; $i < $count; $i++)
{
$test = fgets($f_text)
}
Use % 100 and only print lines where $n % 100 > 0 && $n % 100 <= 10.
$lines = file($text);
foreach ($lines as $n => $line) {
if ($n % 100 > 0 && $n % 100 <= 10) {
echo $line; // or whatever
}
}
A sample of how the logic works:
foreach (range(0,250) as $n => $line) {
if ($n % 100 >= 1 && $n % 100 <= 10 ) {
echo $i . "\n";
}
}
1 2 3 4 5 6 7 8 9 10 101 102 103 104 105 106 107 108 109 110 201 202 203 204 205 206 207 208 209 210
You can easily do this with an SPLFileObject, as long as you know how many lines are in the file:
$file = new SplFileObject( $filename, "r");
$lines = 0;
while ( !$file->eof()) {
$file->fgets();
$lines++;
}
Now you know there are $lines number of lines in the file. If that is static, say 5000, just initialize $lines to 5000. If it's not, let's round that down to the nearest 100:
$lines -= ($lines % 100);
Now, we just loop over every hundred, seek to the grouping of 10, and grab the data we want:
$data = array();
for( $i = 0; $i < $lines; $i += 100) {
$file->seek( $i);
for( $j = 0; $j < 10; $j++) {
$data[] = $file->fgets();
}
}
With this solution, you never load the whole file into memory, which will save resources when dealing with large files. Also, if you know the size of the file beforehand, you will only read the lines of data that you require.
Based on both other answers, probably the most memory-efficient way to do it:
foreach(new SplFileObject($filename) as $n => $line)
if($n % 100 < 10)
echo $line;