I've got a list in a text file with the top 1000 words used in the english language. Each line has a list of up to 50 words, like this:
the,stuff,is,thing,hi,bye,hello,a,stuffs
cool,free,awesome,the,pray,is,crime
etc.
I need to write code using that file as input, to make an output file with the a list of pairs of words which appear together in at least fifty different lists. For example, in the above example, THE & IS appear together twice, but every other pair appears only once.
I can't store all possible pairs of words, so no brute force.
I'm trying to learn the language and I'm stuck on this exercise of the book. Please help. Any logic, guidance or code for this would help me.
This is what I have so far. It doesn't do what's intended but I'm stuck:
Code:
//open the file
$handle = fopen("list.txt", 'r');
$count = 0;
$is = 0;
while(!feof($handle)) {
$line = fgets($handle);
$words = explode(',', $line);
echo $count . "<br /><br />";
print_r($words);
foreach ($words as $word) {
if ($word == "is") {
$is++;
}
}
echo "<br /><br />";
$count++;
}
echo "Is count: $is";
//close the file
fclose($handle);
$fp = fopen('output.txt', 'w');
fwrite($fp, "is count: " . $is);
fclose($fp);
This is what I came up with but I think it's too bloated:
plan:
check the first value of the $words array
store the value into $cur_word
store $cur_word as a key in an array ($compare) and
store the counter (line number) as the value of that key
it'll be 1 at this point
see if $cur_word is on each line and if it is then
put the value into $compare with the key as $cur_word
if array has at least 50 values then continue
else go to the next value of the $words array
if it has 50 values then
go to the next value and do the same thing
compare both lists to see how many values match
if it's at least 50 then append
the words to the output file
repeat this process with every word
There are probably 100's of solutions to this problem. Here is one
$contents = file_get_contents("list.txt");
//assuming all words are separated by a , and converting new lines to word separators as well
$all_words = explode(",", str_replace("\n", ",", $contents));
$unique_words = array();
foreach ($all_words as $word) {
$unique_words[$word] = $word;
}
this will give you all the unique words in the file in an array.
You can also use the same technique to count the words
$word_counts = array();
foreach ($all_words as $word) {
if (array_key_exists($word, $word_counts)) {
$word_counts[$word]++;
} else {
$word_counts[$word] = 1;
}
}
then you can loop through and save the results
$fp = fopen("output.txt", "w");
foreach ($word_counts as $word => $count) {
fwrite($fp, $word . " occured " . $count . " times" . PHP_EOL);
}
fclose($fp);
Related
i am fairly new to PHP and tried several hours to get something going, sadly without a result. I hope you can point me into the right direction.
So what i got is a CSV file containing Articles. They are separated into diff columns and always the same structure, for example :
ArtNo, ArtName, ColorCode, Color, Size
When an article has different color codes in the CSV, the article is simply repeated with the same information except for the color code, see an example:
ABC237;Fingal Edition;48U;Nautical Blue;S - 5XL;
ABC237;Fingal Edition;540;Navy;S - 5XL;
My problem is, i want to display all the articles in a table, include an article image etc.. so far i got that working which is not a problem, but instead of showing the article twice for every different color code i want to create only one line per ArtNo (First CSV Line) but still read the second duplicate line to add the article color to the first one, like :
ABC237; Fingal Edition ;540;Nautical Blue, Navy;S - 5XL;
Is this even possible or am I going into a complete wrong direction here? My code looks like this
<?php
$csv = readCSV('filename.csv');
foreach ($csv as $c) {
$artNo = $c[0]; $artName = $c[1]; $colorCode = $c[2]; $color = $c[3]; $sizes = $c[4]; $catalogue = $c[5]; $GEP = $c[6]; $UVP = $c[7]; $flyerPrice = $c[8]; $artDesc = $c[9]; $size1 = $c[10]; $size2 = $c[11]; $size3 = $c[12]; $size4 = $c[13]; $size5 = $c[14]; $size6 = $c[15]; $size7 = $c[16]; $size8 = $c[17]; $picture = $c[0] . "-" . $c[2] . "-d.jpg";
// Echo HTML Stuff
}
?>
Read CSV Function
<?php
function readCSV($csvFile){
$file_handle = fopen($csvFile, 'r');
while (!feof($file_handle) )
{
$line_of_text[] = fgetcsv($file_handle, 0, ";");
}
fclose($file_handle);
return $line_of_text;
}
?>
I tried to get along with array_unique etc but couldn't find a proper solution.
Read all the data into an array, using the article number as the key....
while (!feof($file_handle) ) {
$values = fgetcsv($file_handle, 0, ";");
$artno = array_shift($values);
if (!isset($data[$artno])) $data[$artno]=array();
$data[$artno][]=$values;
}
And then output it:
foreach ($data as $artno=>$v) {
$first=each($v);
print $artno . "; " . each($first);
foreach ($v as $i) {
$discard=array_shift($i);
print implode(";", $i);
}
print "\n";
}
(code not tested, YMMV)
You need to know exactly how many items belong to each ArtNo group. This means a loop to group, and another loop to display.
When grouping, I steal the ArtNo from the row of data and use it as the grouping key. The remaining data in the row will be an indexed subarray of that group/ArtNo.
I am going to show you some printf() and sprintf() syntax to keep things clean. printf() will display the first parameter's content and using any subsequent values to replace the placeholders in the string. In this case, the 2nd parameter is a conditional expression. On the first iteration of the group, ($i = 0), we want to show the ArtNo as the first cell of the row and declare the number of rows that it should span. sprinf() is just like printf() except it produces a value (silently). Upon any subsequent iterations of the group, $i will be greater than zero and therefore an empty string is passed as the value.
Next, I'm going to use implode() which is beautifully flexible when you don't know exactly how many columns your table will have (or if the number of columns may change during the lifetime of your project).
Tested Code:
$csv = <<<CSV
ABC237;Fingal Edition;48U;Nautical Blue;S - 5XL
ABC236;Fingal Edition;540;Navy;S - 5XL
ABC237;Fingal Edition;49U;Sea Foam;L - XL
ABC237;Fingal Edition;540;Navy;S - 5XL
CSV;
$lines = explode(PHP_EOL, $csv);
foreach ($lines as $line) {
$row = str_getcsv($line, ';');
$grouped[array_shift($row)][] = $row;
}
echo '<table>';
foreach ($grouped as $artNo => $group) {
foreach ($group as $i => $values) {
printf(
'<tr>%s<td>%s</td></tr>',
(!$i ? sprintf('<td rowspan="%s">%s</td>', count($group), $artNo) : ''),
implode('</td><td>', $values)
);
}
}
echo '</table>';
Output:
I am reading a text file and then parse it into a web page. The text file has 3 entries. I want the last entry to show up first, so I am trying to save the text into an array first, and then read it back from the last entry. Seems to me, my $text array is not able to save the string from fgets. I can't figure out what the problem is to the array, and is there a better way to do this?
Here is my php code:
<?php
$test = fopen("test.txt", "r") or die("Unable to open file!");
while (! feof($test)){
$line=fgets($test);
parse_str($line);
$c=$entry;
$text=array("zero--");
if (strncasecmp( $line, "entry", 5)){
$text[$c] .= $line;
echo "c:". $c. $line. "<br>";
}
}
global $text;
echo "t:". $text[0];
echo "t:". $text[1];
?>
Here is the result:
c:1 first entry
c:1 It's sunny today
c:1
c:2 Second entry
c:2 It's sunny today too
c:2 Hi, how are you?
c:2
c:3 last entry
c:3 bye
c:3
t:zero--t:
Here is my test file.
entry=1
first entry
It's sunny today
entry=2
Second entry
It's sunny today too
Hi, how are you?
entry=3
last entry
bye
One approach to show the last entry first is to create an array and for example use the ending digit from entry_1 as the array key. As an array can not have duplicate keys, this should then always be unique.
While reading the lines of the file, you could create an empty array for each key and fill the array. At the end, you could use krsort sort the array by key in reverse order.
$test = fopen("test.txt", "r") or die("Unable to open file!");
$results = [];
while (!feof($test)) {
$line = fgets($test);
if (strncasecmp($line, "entry=", 6) === 0) { //Compare the first 6 characters
$index = intval(substr($line, 6), 10); //$index would be 1, 2 or 3
$results[$index] = []; // Create empty array placeholder to be filled
}
$results[$index][] = $line; // Add the line to the current placeholder
}
krsort($results);
foreach ($results as $result) {
foreach ($result as $item) {
echo $item . "<br>";
}
}
If you want to flatten the array of arrays to 1 array and then use 1 foreach, you could use call_user_func_array and array_merge:
$results = call_user_func_array('array_merge', $results);
foreach ($results as $result) {
echo $result . "<br>";
}
After more than 5 hours code writing and testing and googling, this is my final code that works.
First, it reads the text file into an array using a tag of "entry=", and then it echos from the last position using a for loop. That is it. I also added an if statement to ignore the empty line.
<?php
$new = file("com/test.txt");
foreach ( $new as $a){
parse_str($a);
$c=(integer )$entry;
if (strncasecmp( $a, "entry", 5) !=0){
if(!(ctype_space ( $a ))){
$text[$c] .= $a. "<br>";
}
}
}
for( $i=$c; $i>0; $i--){
echo $text[$i] . "<br>";
}
?>
The code below is a simple version of what I am trying to do. The code will read in two files, see if there is a matching entry and, if there is, display the difference in the numbers for that item. But it isn't working. The first echo displays the word but the second echo is never reached. Would someone please explain what I am missing?
$mainArry = array('Albert,8');
$arry = array('Albert,12');
foreach ($arry as $line) {
$kword = explode(',', $line);
echo 'kword '.$kword[0];
if (in_array($kword[0], $mainArry)) {
echo 'line '.$line. ' has count of '.$kword[1] . '<br>';
}
}
Your $mainArry contains a single element: the string 'Albert,8'. It looks like you want to use it as an array (elements 'Albert' and '8') instead of a string.
You mention the code will read from two files, so you can 'explode' it to a real array, as you do with $arry. A simpler approach would be using str_getcsv() to parse the CSV string into $mainArry.
$inputString = 'Albert,8';
$mainArry = str_getcsv($inputString); // now $mainArry is ['Albert','8']
$arry = array('Albert,12');
foreach ($arry as $line) {
$kword = explode(',', $line);
echo 'kword '.$kword[0];
if (in_array($kword[0], $mainArry)) {
echo 'line '.$line. ' has count of '.$kword[1] . '<br>';
}
}
Test it here.
You are attempting to compare the string Albert with Albert,8, so they won't match. If you want to check if the string contains the keyword, assuming your array has more than one element, you could use:
$mainArry = array('Albert,8');
$arry = array('Albert,12');
foreach ($arry as $line) {
$kword = explode(',', $line);
echo 'kword '.$kword[0];
foreach ($mainArry as $comp) {
if (strstr($comp, $kword[0])) {
echo 'line '.$line. ' has count of '.$kword[1] . '<br>';
}
}
}
example: https://eval.in/728566
I don't recommend your way of working, but this is a solution, basically the process you apply to the $arry should also apply to the $mainArry you're trying to compare it to.
$mainArry = array('Albert,8');
$arry = array('Albert,12');
/***
NEW function below takes the valus out of the main array.
and sets them in their own array so they can be properly compared.
***/
foreach ($mainArry as $arrr){
$ma = explode(",",$arrr);
$names[] = $ma[0];
$values[] = $ma[1];
}
unset($arrr,$ma);
foreach ($arry as $line) {
$kword = explode(',', $line);
echo 'kword '.$kword[0];
/// note var reference here is updated.
if (in_array($kword[0], $names)) {
echo '<br>line '.$kword[0]. ' has count of '.$kword[1] . '<br>';
}
}
Yeah, MarcM's answer above does the same thing in a neat single line, but I wanted to illustrate a little more under the hood operations of the value setting. :-/
<?php
// Open the file
$filename = 'pvemail.txt';
$fp = fopen($filename, 'r');
// Add each line to an array
if ($fp) {
$array = explode("\n", fread($fp, filesize($filename)));
}
//print_r ($array);
for ($c = 0; $c < count($array); $c++){
$cell = explode(",", $array[$c]);
print_r ($cell);
echo '<br/>';
}
?>
I am currently working on this code. I have taken a text file generated from a Google report, and managed to explode it into an array, and then I've taken each element of the array and exploded that into another array. However, the problem I'm now having is I only want to retrieve 3 elements of the second exploded array and there are 20 elements to each array.
What would be the best way to go about this, should I use a for or foreach loop? I only need to print $cell[2], $cell[11] and $cell[12]. I have tried using:
echo ($cell[2] + " " + $cell[12] + " " + $cell[11]
($cell[11] and $cell[12] are in this order because 11 is a last name and 12 is a first name and I want the first name first so I've had to put them backwards) but when I run that piece of code it just outputs line breaks and 0's. I'm really just wondering what would be the most effective method of looping through the arrays, and should I do it within the loop that I have already established?
I was thinking that if I were to put it inside my existing for loop I could use an if/else loop, something like:
if($cell = $cell[2]){
echo ($cell[2])
};
but i'm not convinced this will work. Should I define a variable to store $cell[2], [11] and [12] in, and create my if loop based on that, and then I would only need to echo the variable? Is that likely to be effective? Any help would be appreciated, I've looked around on the forum for posts similar to this but I haven't been able to find anything.
20130912,b875c9b154cf7b8d,el#pv-eu.com,ACTIVE,30720,1054180015,,,20100902,20130910,20130904,L,E,,,,20130911,2010-09-02 09:11:37,2013-09-10 23:51:21,2013-09-04 03:06:09,2013-09-11 00:41:24
20130912,66c63753b8188f17,lf#pv-eu.com,ACTIVE,30720,3699701524,,,20110315,20130911,20130911,F,L,,,,19691231,2011-03-15 02:00:31,2013-09-11 00:50:17,2013-09-11 00:52:16,1969-12-31 16:00:00
20130912,bd5ef40689adf9ac,ah#pv-eu.com,ACTIVE,30720,3476851137,,,20110426,20130911,20130910,H,A,,,,20110720,2011-04-26 01:47:56,2013-09-11 16:58:48,2013-09-10 06:20:26,2011-07-20
This is how the text file itself looks, although there is a lot more data. All I'm trying to pull is the email address and name.
Assuming pvemail.txt is a CSV file, does this solve your problem?
$content = file_get_contents('pvemail.txt');
$lines = explode("\n", $content);
header('Content-type: text/plain');
foreach($lines as $line) {
$values = explode(',', $line);
echo $values[2], ' ', $values[12], ' ', $values[11], "\n";
}
Using the 3 sample lines, the above code outputs this:
el#pv-eu.com E L
lf#pv-eu.com L F
ah#pv-eu.com A H
My aim is to create a sentence consisting of three random words which are to be taken from the columns of a CSV file.
I am having troubles with making PHP choose the words only from the correct columns, hence column one contains the words to be first in the sentence, column two only middle words and column three only last words.
Example of the CSV file:
my;horse;runs
your;chicken;sits
our;dog;barks
Example of the output:
My chicken barks. *reload*
Your horse sits. *reload*
Our dog runs.
My effort so far:
<?php
$file = fopen('input.csv', 'r');
while (($line = fgetcsv($file, 1000, ";")) !== FALSE) {
$x = array_rand($line);
echo $line[$x] . "\n";
}
?>
Thanks in advance and forgive the strong noobness with this one, please.
This gives randomized sentences as requested:
<?php
$file = fopen('input.csv', 'r');
// prepare token contained
$line = array();
// read csv file line by line
while (!feof($file))
// fill single line into token container
$line[] = fgetcsv($file, 1000, ";");
// construct a sentence by picking random words from columns
$sentence = sprintf("%s %s %s\n",
$line[rand(0,sizeof($line)-1)][0],
$line[rand(0,sizeof($line)-1)][1],
$line[rand(0,sizeof($line)-1)][2] );
// output sentence
echo $sentence;
?>
However it is not very efficient, since it reads the whole csv file into memory first. So it only performs on smaller csv files (say up to a few hundred lines). For bigger files you should consider picking the random line number first and reading only that line from the file. Doing this three times gives you three words you can constrcut your sentence from.
I would sort the columns into separate arrays then select a random index.
<?php
$file = fopen('input.csv', 'r');
while (($line = fgetcsv($file, 1000, ";")) !== FALSE) {
$column1[] = $line[0];
$column2[] = $line[1];
$column3[] = $line[2];
}
function pickWord($wordArray){
$x = array_rand($wordArray);
echo $wordArray[$x] . "\n";
}
pickWord($column1);
pickWord($column2);
pickWord($column3);
?>
Something like that
Code
<?php
$csv = "my;horse;runs
your;chicken;sits
our;dog;barks";
$lines = explode( "\n", $csv );
foreach( $lines as $line ) {
echo ucfirst( str_replace( ";", " ", trim( $line ) ) ) . "<br />";
}
?>
Output
My horse runs
Your chicken sits
Our dog barks