What is the best way to calculate the frequency of a specific word in an array?

I have been attempting to eliminate duplicates from my array and determine the frequency of each word appearing in the array. While I have come across methods to address this issue, none of them seem to be working. For instance, when I input the text "this this is a test test," the final sorted list is:

1 - is

1 - a

2 - this

2 - test

Although I intend to eventually reverse the array so that the highest numbers appear first, this result is exactly what I am looking for! However, changing the text slightly to something like "this is a test test this" completely disrupts the order:

1 - this

1 - is

1 - a

1 - this

2 - test

Here, 'test' appears twice as expected, but 'this' shows up twice in the list with a count of '1' each time. This only occurs for consecutive duplicates. How can this be prevented?

Below is the code snippet I am currently using:

<!DOCTYPE html>
<html>
<body>

<p>Click the button to display the array values after splitting.</p>

<button onclick="analyze()">Analyze</button>

<p id="displayText"></p>

<script>
function compareWordCount(a,b) {
  if (parseInt(a) < parseInt(b))
    return -1;
  return 1;
}

function analyze() {
    var str = "this is a test test this";
    var res = str.split(" ");
    document.getElementById("displayText").innerHTML = res;
    document.getElementById("displayText").innerHTML += "<br/><br/>The number of words is: " + res.length + "<br/><br/><br/>";

    document.getElementById("displayText").innerHTML += "The list of words:<br/><br/>";

    var words = [];

    var wordsWithCount = [];

    for (i = 0; i < res.length; i++) {
        words.push(res[i]);
        document.getElementById("displayText").innerHTML += words[i] + "<br/><br/>";
    }

    var current = null;
    var cnt = 0;
    for (var i = 0; i < words.length; i++) {
        if (words[i] != current) {
            if (cnt > 0) {
                document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
                wordsWithCount.push(cnt + " - " + current);
            }
            current = words[i];
            cnt = 1;
        } else {
            cnt++;
        }
    }

    if (cnt > 0) {
        document.getElementById("displayText").innerHTML += "<br/><br/>" + cnt + " - " + current + "<br/>";
        wordsWithCount.push(cnt + " - " + current);
    }

    wordsWithCount.sort(compareWordCount);

    document.getElementById("displayText").innerHTML += "<br/><br/><br/><br/><br/>The list of SORTED words:<br/><br/>";

    for (i = 0; i < wordsWithCount.length; i++) {
        document.getElementById("displayText").innerHTML += wordsWithCount[i] + "<br/><br/>";
    }
}
</script>

</body>
</html>

Answer №1

Below is a potential resolution using a combination of the for loop and Array.prototype.forEach() method:

let sentence = "One Two Three One One Three Two One Two Three",
    words = sentence.split(' '),
    result = {},
    count = 0;
    
for (let i = 0; i < words.length; i++) {
  count = 0;
  words.forEach(function (word) {
    if (word === words[i]) {
      count++;
    }
  });
  if (!result[words[i]]) {
    result[words[i]] = count;
  }
}

console.log(result);

Answer №2

GSerg's observation about this being a duplicate seems valid, but let's delve into the logic behind your code to clarify what's happening step by step:

Initially, you break down the string this is a test test this into an array:

words = [this, is, a, test, test, this]

As you loop through the array, you compare each word to the previous one. If they match, you increment a counter. If not, you add the previous word to the wordsWithCount array.

The issue arises when you encounter the second occurrence of this in the array. The problem stems from starting a new counter for the second instance instead of continuing with the existing one.

To address this, consider using a key-value structure like this:

for (var i = 0; i < words.length; i++) {
    if(wordsWithCount[words[i]] === undefined) {
        wordsWithCount[words[i]] = 1;
    } else {
        wordsWithCount[words[i]]++;
    }
}

This approach yields the desired structure:

wordsWithCount: {
    'this': 2,
    'is': 1,
    'a': 1,
    'test': 2
}

You can then iterate through this structure to generate the formatted list you mentioned:

var formattedWordsWithCount = [];
for (var word in wordsWithCount) {
    formattedWordsWithCount.push(wordsWithCount[word] + " - " + word);
}

Answer №3

Utilize an object to keep track of the frequency of each word:

    var sentence = "this is a test test this";
    var wordsArray = sentence.split(" ");
    var wordFrequency = {};

    for (var i = 0; i < wordsArray.length; i++) {
        var currentWord = wordsArray[i];
        if (currentWord in wordFrequency) {
            wordFrequency[currentWord]++;
        } else {
            wordFrequency[currentWord] = 1;
        }
    }

    console.log("WORD FREQUENCY");

    for (currentWord in wordFrequency) {
        console.log(currentWord + " - " + wordFrequency[currentWord]);
    }
    
    var sortedWords = [];
    for (var currentWord in wordFrequency) {
        sortedWords.push([currentWord, wordFrequency[currentWord]]);
    }
    
    sortedWords.sort(function(a, b) {
        return b[1] - a[1];
    });
    
    console.log("SORTED WORD FREQUENCY");
    
    for (var i = 0; i < sortedWords.length; i++) {
        var word = sortedWords[i][0];
        console.log(word + " - " + wordFrequency[word]);
    }

Answer №4

Check out this clever solution that can handle case sensitivity and punctuation.

function cleanWord(word) {
  let cleaned;
  const regex = /(\w+)/g.exec(word.toLowerCase().trim());
  if(regex) {
    cleaned = regex[1];
  }
  return cleaned;
}

function countWords(str) {
  let wordCount = {};
  str.split(" ").forEach((word) => {
    word = cleanWord(word);
    if(word) {
      if (wordCount.hasOwnProperty(word)) {
        wordCount[word] = wordCount[word] + 1;
      } else {
        wordCount[word] = 1;
      }
    }
  });
  return wordCount;
}

console.log(countWords("This, . is a test! test this this"));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Encountering a 500 internal server error with jQuery and WordPress

I'm having issues implementing ajax into my WordPress project to dynamically load videos based on their post ID. Whenever I click on the video link, a 500 internal server error occurs. I'm sending the post ID through ajax to a PHP script where I ...

Can the MemoryRouter be successfully nested within the BrowserRouter in a React application?

I've been on a quest for some time now, trying to uncover whether it's feasible to utilize MemoryRouter solely for specific routes while maintaining the use of BrowserRouter in general. My goal is to navigate to a particular component without alt ...

The error message states that the provided callback is not a valid function -

I seem to be encountering an issue with the code snippet below, which is part of a wrapper for the Pipl api: The main function here performs a get request and then retrieves information from the API Any assistance in resolving this error would be greatly ...

After the child promise is resolved, have the parent function return a boolean value

I am currently faced with a challenge in my framework where the parent function must output either true or false>. However, I also need to perform an asynchronous operation within that function.</p> <p>How can I ensure that the parent functi ...

When a user clicks a button, modify a section of the URL and navigate to

I've been searching everywhere for a solution to this issue, but I just can't seem to find it. I'm hoping someone here can help me out. In a bilingual store, I need a way to redirect users to the same product on a different domain when they ...

The loading time for the NextJS production build is unacceptably sluggish

Recently, I started working with NextJS and deployed my project on Netlify as a production build. However, I've noticed that there is a significant delay of around 3-4 seconds when navigating to a specific page using the next router. Surprisingly, thi ...

Is there a way to detect when a Bootstrap Alert is displayed?

I am using a flask app that flashes messages to an HTML file. When these flashed messages are caught, they are displayed as a bootstrap alert. Here is an example: {% with messages = get_flashed_messages() %} {% if messages %} {% for message in mes ...

Error: The specified module could not be found: Could not resolve 'react-hot-loader/webpack'

After constructing my React project, I encountered the error shown below. How can I resolve this issue? I am utilizing the latest version of react-hot-loader. I have attached a screenshot of the error here ...

individual elements displayed sequentially within the same block with variable naming

My code caters to both mobile and desktop versions, with the same elements in the FORM. However, only one block of code is visible at a time depending on the screen size, with one set to display: none. <div id="desktop"> <div id="content"> ...

Tips for arranging various information into a unified column within an Antd Table

Is there a way to display multiple data elements in a single cell of an Ant Design table, as it currently only allows insertion of one data element? I am attempting to combine both the 'transactionType' and 'sourceNo' into a single cell ...

Utilizing Numpy Arrays: Extract multiple values at specific intervals

Is there a way to extract multiple values at once from an array in Numpy using a one-liner? For example, if we have an array: a = numpy.arange(10) > array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) I want to extract 2 values, skip the next 2 values, and then ext ...

In C, arrays have the ability to store values beyond their defined boundaries

Hey there, I'm currently working on implementing bubblesort in C and have hit a roadblock that I'm struggling to overcome. #include <stdio.h> #include <time.h> void main(){ int i; int j; int vahe; int sisse; i ...

Encountered Node.js & MySQL error: 1251 - Client not able to support authentication protocol requested by server. It is recommended to upgrade MySQL client for resolving this

I currently only have the following code snippet: const Sequelize = require('sequelize'); const sequelize = new Sequelize('database', 'root', 'passwd', { host: 'localhost', dialect: 'mysql', ...

Having trouble properly displaying information from a JSON array with jQuery

Having a basic array of data in a JSON file is presenting a challenge for a beginner like me when it comes to extracting the data. Here is the array that I have access to: var clients = [ { "clientid": "456489", "client-name": "John Smith", "e ...

What is the method to determine the inviter on Discord.js?

Hi there! I'm currently working on an Invite Logger and could use some assistance. I'm having trouble figuring out how to identify the user who invited another user. client.on('guildMemberAdd', async (member) => { const channel = ...

Repeated instances of the same name appearing in the dropdown list every time the tab button is clicked

When using my function in the onclick nav tabs event (triggered by clicking on any tab), I have a requirement where I need to ensure that no duplicate names are inserted into the dropdown list. The current function is working perfectly, but I am looking fo ...

Use Angular to assign a value to a radio button after it has been clicked by a button

I am working with a group of radio buttons that display different content when clicked. <div class="radio" ng-init="topRadios()"> <input type="radio" ng-model="topTable" value="topCategory" ng-change="updateTotals('topCategory')">TY ...

AngularJS directive that allows for either a click action to be passed or a ui-router state change to

I have a button (an a tag) that is displayed in multiple locations on my website. It is labeled "View Demo", and sometimes it directs to a demo page using an ui-sref: <a class="btn btn-primary" ui-sref="hamburger-push" target="_blank"> View Demo ...

Can you show me how to use jQuery/JS to split this string into two separate arrays?

Can you help me separate this string into two arrays? { array1: [ 'mary', 'steve', 'george' ], array2: [ 'dog', 'cat', 'hobbit' ] } I attempted the following code but encountered a syntax err ...

How can I retrieve the body from a GET request using Express?

Every time I attempt to execute my code, it returns an error message indicating invalid text. app.post("/charge", (req, res) => { console.log(req.body) }) ...