2

Please check this fiddle: https://jsfiddle.net/dp0y4hrw/16/

This is JS to find longest compound word in an array of strings.

Instead of an array, I want this program to read a local txt file, consisting of over 100,000 lines of text. Then find longest compound words. Each line has one word.

I've tried using FileReader to get the data. I was able to correctly pass the data, but gave me trouble with some shared variables between 'addPrefix' and 'findPrefixes'.

I also tried using a promise, to account for the asynchronous behavior:

function readFile(event) {  
  var file = event.target.files[0]; 

  if (file) {   
    new Promise(function(resolve, reject) {      
      var reader = new FileReader();      
      reader.onload = function (evt) {      
      resolve(evt.target.result);      
      };     

      reader.readAsText(file);     
      reader.onerror = reject;   
     })    

     .then(findLongestWord)   
     .catch(function(err) {     
       console.log(err)
     });  
   }
 }

document.getElementById('file').addEventListener('change', readFile, false);

function findLongestWord(data) {
...

This still gives me an issue. What would be the best way to read the file so I can process the contents correctly in this situation?

EDIT:

// adds word as a prefix
var addPrefix = function (word) {
  var i  = 0;
  var current = prefixes;
  var char;

  while (char = word[i++]) {
    if (!current[char]) {
      current[char] = {};
    }
      current = current[char];      
  }
  current.word = true;
  return current.word; //RETURNING CURRENT WORD HERE
};

// Finds the longest prefix we can make using the word.
var findPrefixes = function (word) {
  var prefix = '';
  var current = prefixes;
  var found  = [];
  var i  = 0;
  var char;

  while (char = word[i++]) {
    if (!current[char]) { 
      break; 
    }
    // Move to the next character and add to the prefix.
    current = current[char];
    prefix += char;

    if(current.word)
    {
      found.push(prefix);
    }
  }
  return found;
};

//for each word in list, add to prefix
list.forEach(function (word) {
  var prefix;

// If we can find a closest possible word, it may be possible to create a
// compound word - but we won't be able to check until we reach the end.
if ((prefix = findPrefixes(addPrefix())) && prefix.length) { //FINDPREFIXES USING ADDPREFIX HERE
  prefixMatch.push([ word, prefix ]);

}

// Insert the word into the prefix tree.
addPrefix(word);
});

EDIT 2: This is example of input text file:

cat
cats
catsdogcats
dog
dogcatsdog
hippopotamuses
rat
ratcatdogcat
catratdograt
dogcatscats

Expected result is: longest: ratcatdogcat,catratdograt...2nd longest: catsdogcats,dogcatscats...number of compound words: 5

36
  • What issue are you having with javascript at Question and linked jsfiddle? Commented Sep 19, 2016 at 3:43
  • @guest271314 the issue is I want to be able to read external text file data through readFile(event) but when I implement it like that, 'current.word' object.key does not get shared between addPrefix and findPrefixes. So function doesn't work. Commented Sep 19, 2016 at 3:46
  • " 'current.word' object.key does not get shared between addPrefix and findPrefixes" Which function should be called first? What is expected result value of first function which should be called and expected parameter passed to second function? What is expected return value of second function? Commented Sep 19, 2016 at 3:49
  • @guest271314 findPrefix is called first, then addPrefix. How it is set up currently, say "word" is passed. The function is stacking objects inside of other objects, and only the last one has the property 'word'. Ex: if your text file only has "word" in it, your current variable will be like this: '{"w":{"o":{"r":{"d":{"word":true}}}}}' . That means current.word will only be true when at end of the word. That way we can push 'word' into found array. Commented Sep 19, 2016 at 3:55
  • 1
    @guest271314 how man. I'm at a loss for words. i can't thank you enough. how can i give you more than just +1 reputation? thank you for sticking with me for over an hour. it works. not sure what the regex is doing here tho lol Commented Sep 19, 2016 at 5:41

1 Answer 1

2

Use RegExp /\w+/g

\w Matches any alphanumeric character from the basic Latin alphabet, including the underscore.

x+ Matches the preceding item x 1 or more times

var list = data.match(/\w+/g);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.