Pathros
Pathros

Reputation: 10730

php array_filter works into functions but not inside a class as a method

I have this code where I want to get the most frequent words from a text. I use several array functions such as str_word_count(), array_count_values(), and finally array_filter(). Here is the code as follows:

<?php
/*Get the most frequent words with PHP*/

/*1. Assign the text to a variable*/
$text='NOT long ago, many parents wondered at what age they should give their child full access to the car keys. Nowadays, parents face a trickier question: At what age should a child own a smartphone?

The smartphone, after all, is the key to unfettered access to the internet and the many benefits and dangers that come with it. But unlike driving a car, which is legal in some states starting at the age of 16, there is no legal guideline for a parent to determine when a child may be ready for a smartphone.

The topic is being increasingly debated as children get smartphones at an ever younger age. On average, children are getting their first smartphones around age 10, according to the research firm Influence Central, down from age 12 in 2012. For some children, smartphone ownership starts even sooner — including second graders as young as 7, according to internet safety experts.';    
echo $text;
/*2. Set to lowercase*/
$text = strtolower($text);
/*3. Separate the text into words, into an array. Accept foreign ascii characters*/
$words = str_word_count($text,1,'áâæàåãäçéêèëíîìïñóôòøõöœúûùüÿ¿¡');
echo '<br><hr><h3>Words:</h3>';
if(is_array($words)){echo '<p>$words is indeed an array</p>';}
var_dump($words);
/*3. Get each word's occurrences'*/
$words = array_count_values($words);
echo '<br><hr><h3>Words occurrences:</h3>';
var_dump($words);
/*4. Order according to occurrences*/
echo '<br><hr>';
arsort($words);
var_dump($words);
echo '<br><hr>';
/*5. Defining the stopwords*/
//Stopwords:
$stopwords = ['the','to','it','is','a','at','for','as'];
/*6. Filter out the stopwords and those words with a frequence not more than 2 occurrences*/
$palabras = array_filter($words, function($word,$index)use($stopwords){
    if(!in_array($index,$stopwords)){
        if($word>2){
            return true;
        }
    }
},ARRAY_FILTER_USE_BOTH);

echo '<p>Now the most frequent words are (without the stop words):</p>';
var_dump($palabras);
?>

It's working fine. Now I want to pass this code into a class.

Here is the code of the class and instantiation:

<?php
/*Class to get the most frequent words from a text*/
namespace Models\Helpers\TextMining;

class Word
{
    protected $text;
    protected $words=[];
    protected $filtered_words=[];
    protected $stopwords = [];
    protected $lang;
    protected $active;
    protected $ascii = 'áâæàåãäçéêèëíîìïñóôòøõöœúûùüÿ¿¡';

    public function __construct($text,$lang = 'es',$active = true)
    {
        $this->text = strtolower($text);
        $this->words = str_word_count($this->text,1,$this->ascii);
        $this->lang = $lang;
        $this->active = $active;
        $this->stopwords = ['the','to','it','is','a','at','for','as'];
        arsort(array_count_values($this->words));
    }

    /*Show stopwords*/
    public function getStopwords(){
        return $this->stopwords;
    }
    /*Show the words from the text*/
    public function getWords()
    {
        return $this->words;
    }

    /*Filter out the stopwords from the text and those words with an occurrence not greater than 2*/
    public function applyStopwords2text()
    {
        $stopwords = $this->getStopwords();
        $words = $this->getWords();

        $palabras = array_filter($words, function($word,$index)use($stopwords){
            if(!in_array($index,$stopwords)){
                if($word>2){
                    return true;
                }
            }
        },ARRAY_FILTER_USE_BOTH);

        $this->filtered_words = $palabras;
        return $palabras;
    }
}

/***************/
    $text='NOT long ago, many parents wondered at what age they should give their child full access to the car keys. Nowadays, parents face a trickier question: At what age should a child own a smartphone?

The smartphone, after all, is the key to unfettered access to the internet and the many benefits and dangers that come with it. But unlike driving a car, which is legal in some states starting at the age of 16, there is no legal guideline for a parent to determine when a child may be ready for a smartphone.

The topic is being increasingly debated as children get smartphones at an ever younger age. On average, children are getting their first smartphones around age 10, according to the research firm Influence Central, down from age 12 in 2012. For some children, smartphone ownership starts even sooner — including second graders as young as 7, according to internet safety experts.';

    $word = new Word($text,'es',true);
    $stopwords = $word->getStopwords();
    var_dump($stopwords);
    //var_dump($word);
    //die();
    $words = $word->applyStopwords2text();

    var_dump($words);


?>

The problem is with the array_filter() function, because I get an empty array. Nothing is stored inside the property protected $filtered_words=[]; when using the same array_filter() function. Why? How do I fix this?

Upvotes: 1

Views: 478

Answers (2)

BVengerov
BVengerov

Reputation: 3007

It seems that you've made a small mistake in your constructor method. Try this:

public function __construct($text,$lang = 'es',$active = true)
{
    $this->text = strtolower($text);
    $this->words = str_word_count($this->text,1,$this->ascii);
    $this->lang = $lang;
    $this->active = $active;
    $this->stopwords = ['the','to','it','is','a','at','for','as'];
    $this->words = array_count_values($this->words);
    arsort($this->words);
}

As you see, the result of array_count_values is not assigned to $this->$words, so you still have your old words array when you call the filter function.

Upvotes: 3

davidsheldon
davidsheldon

Reputation: 40055

Your problem is in your constructor - you haven't made the code do the same as in the stand-alone version.

In the last line:

arsort(array_count_values($this->words));

The result of array_count_values isn't assigned to anything, so arsort sorts the temporary array, and then doesn't save it.

Change your constructor to:

public function __construct($text,$lang = 'es',$active = true)
{
    $this->text = strtolower($text);
    $this->words = str_word_count($this->text,1,$this->ascii);
    $this->lang = $lang;
    $this->active = $active;
    $this->stopwords = ['the','to','it','is','a','at','for','as'];
    $this->words = array_count_values($this->words);
    arsort($this->words);
}

Then it will match the non-oop version of the code.

Upvotes: 2

Related Questions