merging arrays and word frequency - php

So I'm cycling through a document with 41 paragraphs. For each paragraph I'm trying to [1] first break the string into an array, and then get the word frequency of the paragraph. I then want to combine the data from all paragraphs and get the word frequency of the whole document.
I'm able to get array that gives me the "word" and its "frequency" for a given pargraph but I'm having trouble merging the results from each paragraph so as to get the "word frequency of the whole document. Here is what I have:
function sectionWordFrequency($sectionFS)
{
$section_frequency = array();
$filename = $sectionFS . ".xml";
$xmldoc = simplexml_load_file('../../editedtranscriptions/' . $filename);
$xmldoc->registerXPathNamespace("tei", "http://www.tei-c.org/ns/1.0");
$paraArray = $xmldoc->xpath("//tei:p");
foreach ($paraArray as $p)
{
$para_frequency = (array_count_values(str_word_count(strtolower($p), 1)));
$section_frequency[] = $para_frequency;
}
return array_merge($section_frequency);
}
/// now I call the function, sort it, and try to display it
$section_frequency = sectionWordFrequency($fs);
ksort($section_frequency);
foreach ($section_frequency as $word=>$frequency)
{
echo $word . ": " . $frequency . "</br>";
}
Right now the result I get is:
1: Array
2: Array
3: Array
4: Array
Any help is greatly appreciated.

Try to replace this line
$section_frequency[] = $para_frequency;
with this
$section_frequency = array_merge($section_frequency, $para_frequency);
and then
return $section_frequency

Related

How to remove, just once, a word that appears several times in the array

I've researched all sorts of ways, but I haven't found a solution for this case.
Basically I have to see if the word repeats and just remove the first occurrence of it in the array. For example:
$array_words = ['harmony', 'Acrobat', 'harmony', 'harmony'];
How do I check the repeated word, just once, leaving the array like this:
$array_final = ['Acrobat', 'harmony', 'harmony'];
I threw together this simple loop, and explained it with comments
$array_words = ['harmony', 'Acrobat', 'harmony', 'harmony'];
//get a count of each word in the array
$counted_values = array_count_values($array_words);
//hold the words we have already checked
$checked_words = [];
//variable to hold our output after filtering
$output = [];
//loop over words in array
foreach($array_words as $word) {
//if word has not been checked, and appears more than once
if(!in_array($word, $checked_words) && $counted_values[$word] > 1) {
//add word to checked list, continue to next word in array
$checked_words[] = $word;
continue;
}
//add word to output
$output[] = $word;
}
$output value
Array
(
[0] => Acrobat
[1] => harmony
[2] => harmony
)
GrumpyCrouton's solution is probably neater, but here's another way. Basically you put all the values into a single string, and then use string functions to do the work.
Code is commented with explanatory notes:
<?php
$array_words = ['harmony', 'Acrobat', 'harmony', 'harmony'];
$array_words_unique = array_unique($array_words); //get a list of unique words from the original array
$array_str = implode(",", $array_words);
foreach ($array_words_unique as $word) {
//count how many times the word occurs
$count = substr_count($array_str, $word);
//if it occurs more than once, remove the first occurence
if ($count > 1) {
//find the first position of the word in the string, then replace that with nothing
$pos = strpos($array_str, $word);
$array_str = substr_replace($array_str, "", $pos, strlen($word));
}
}
//convert back to an array, and filter any blank entries caused by commas with nothing between them
$array_final = array_filter(explode(",", $array_str));
var_dump($array_final);
Demo: https://3v4l.org/i1WKI
Credit to Using str_replace so that it only acts on the first match? for code to replace only the first occurence of a string inside another string.
We can use an array to keep track of each item that has been removed, and then use array_shift to move out of the item and count to limit loop overruns
<?php
$record = ['harmony','harmony', 'Acrobat', 'harmony', 'harmony','last'];
for($i=0,$count=count($record),$stack=array();$i<$count;$i++){
$item = array_shift($record);
in_array($item,$record) && !in_array($item,$stack)
? array_push($stack,$item)
: array_push($record,$item);
}
var_dump($record);

PHP & CSV - Echo Result only once

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:

Php string not saving into arrary

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>";
}
?>

PHP: Creating an associative array programmatically

I have a return string from a 3rd party plugin that looks like a var_dump from an array. I'm trying to parse into a valid associative array. Looking at various examples and doing some tests with the code that follows. The last segment demonstrates the problem I'm having. I'm trying to parse out the data into a string and then programmatically create an array after my data string has been finished. When I do a print_r on $vegetables2, I get:
Array([0] => “Gourd”=”40 kilojoules”,”Artichoke”=”105 kilojoules”,”Cassava”=”550 kilojoules”)
And the echo $vegetables2["Artichoke"] produces no value. Can someone please guide me at the correct syntax to create the array equivalent to the first two examples?
//this works:
echo "From creating the entire array with a static string:<br/>";
$vegetables = array("Gourd"=>"40 kilojoules", "Artichoke"=>"105 kilojoules", "Cassava"=>"550 kilojoules");
echo "Artichoke: " . $vegetables["Artichoke"] . "<br/>";
//this works too
$vegetables1['Gourd'] = "40 kilojoules";
$vegetables1['Artichoke'] = "105 kilojoules";
$vegetables1['Cassava'] = "550 kilojoules";
echo "From creating one element at a time:<br/>";
echo "Artichoke: " . $vegetables1["Artichoke"] . "<br/>";
//this doesn't work
$strData = "\"Gourd\"=\"40 kilojoules\",";
$strData = $strData . "\"Artichoke\"=\"105 kilojoules\",";
$strData = $strData . "\"Cassava\"=\"550 kilojoules\"";
echo $strData ."<br/>";
$vegetables2 = array($strData);
print_r($vegetables2);
echo "Artichoke: " . $vegetables2["Artichoke"];
$strData = "\"Gourd\"=\"40 kilojoules\",";
$strData = $strData . "\"Artichoke\"=\"105 kilojoules\",";
$strData = $strData . "\"Cassava\"=\"550 kilojoules\"";
$dd=str_replace('"','',"$strData");
$ff=explode(',',$dd);
foreach ($ff as $c)
{
$xx=explode('=',$c);
$vegetables2["$xx[0]"]=$xx[1];
}
print_r($vegetables2);
echo "Artichoke: " . $vegetables2["Artichoke"];
This string is your input:
"Array ( [Gourd] => 40 kilojoules [Artichoke] => 105 kilojoules [Casava] => 550 kilojoules )"
use strpos() to locate "("
use strpos() to locate ")"
use substr() to get what is between ( and )
use explode to divide the result wherever "[" appears
use array() to start a new array
use foreach to reformat each piece
use explode to divide each piece wherever "=>" appears
use trim to remove excess characters (left and right)
use $data[$key] = $value to create a new array to your liking

Understand PHP arrays

I'm a newbie and I have a very basic question about PHP arrays
Code:
While(!feof($file_handle))
{
$SecondRow = fgets($file_handle); //gets row
$trimmed = trim($SecondRow); //removes extra bits
$replace = array("'");
$finalstring = str_replace($replace, "_", $trimmed); //Still a string w/o "'"'s
$CleanString = preg_split("/[\s]*[,][\s]*/", $finalstring); //creates the array
//print_r($CleanString);
echo "Row " . $CleanString[1]. "<br/>"; //??????
.....
}//end while
the opened file has the following:
0001,sparta
0005,PURCHASING
...
...
...
Question:
When I echo "Row " . $array[0], I get the first column as expected. But when I echo "Row " . $array[1], I get an the "Undefined offset: 1" error. When the string is read into the array (via preg_split) aren't both
array[0]->0001 and array[1]->sparta set?
thanks.
Looking at your entire code, you're essentially replicating a native function like fgetcsv() or one of it's equivalents.
Just pick one and be done :)
As far as determining how to use the array, as noted in the comments use print_r or var_dump() to guide you. Also read up on PHP Arrays
This is because fgets() get one row at time (one row per "loop").

Categories