1

The goal of my application is simple:

  • Accept a random number parameter
  • Read the dictionary.txt file
  • turn that file into an array by taking each word in the file (each word is on a new line in the file)
  • push each array item created into an object and then have itself as a word property

At the point I have the object created, my aim is to get a random word from that object, for example:

outputObj[randNum].word

Which should return the word at the index I set in the randNum parameter and the value stored in its word property.

I am getting confused and have tried everything I can think of to achieve the end result.

Here is my current JS:

var fs = require('fs),
    getWordFromRandomNumber = function(randNum) {
        var output = fs.readFileSync('../dictionary/dictionary.txt', 'utf8')
            .trim()
            .split('\r\n')
            .map(line => line.split('\r\n'))
            .reduce(function(outputObj, line){
            outputObj[line] =  outputObj[line] || [];
            outputObj[line].push({
                word: line,
            });
            return outputObj[randNum].word;
        }, {});


        console.log(JSON.stringify(output, null, 2));
    }

getWordFromRandomNumber(25);

I expect this to return to me the value of outputObj[25].word but all I get is a cascade of the whole file, see here (note I am using my cmd to run the file using babel and node with the command "babel wordGenerator.js | node":

enter image description here

Any help would be much appreciated as I am all out of ideas at the moment.

Thanks, SD

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • you should be splitting by \r\n not /n – kennypu Oct 28 '15 at 22:41
  • fixed that as you can now see but still not returning what I want it to. –  Oct 28 '15 at 22:45
  • `babel` is a *"Python internationalization library with an emphasis on web-based applications."*... are you really using that library? I don't imagine it works on JavaScript files. – Felix Kling Oct 28 '15 at 22:47
  • it does, it is an emulator for js files in node, I use it all the time and it is never an issue, all it does is output console.logs into the cmd, it could do more but thats all I use it for anyhow. –  Oct 28 '15 at 22:48
  • Are you sure you don't mean `babeljs`: *"Babel (formerly 6to5) is a JavaScript compiler. It transforms ES6+/ES2015 code into ES5 code."* ? – Felix Kling Oct 28 '15 at 22:49
  • there is more than one babel? I never knew. but yeah, babeljs: https://babeljs.io/docs/usage/cli/ –  Oct 28 '15 at 22:50
  • Also I don't think you are fully aware of how reduce works. Check the documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce – Felix Kling Oct 28 '15 at 22:50
  • Always read the tag description. The one for `babel` is *"Python internationalization library with an emphasis on web-based applications. For questions about the JavaScript library, please use [babeljs]."* Either way, this doesn't have anything to with babel itself, so it doesn't even make sense to tag it. Also https://en.wikipedia.org/wiki/Babel . – Felix Kling Oct 28 '15 at 22:51
  • I didnt realise, will do next time. Still, my issue still stands and its quite annoying because I can't figure it out still. –  Oct 28 '15 at 22:53
  • Ugh, where did you get a \r\n delimited text file? :-( – James M Oct 28 '15 at 22:55
  • from the pits of hell itself I think. –  Oct 28 '15 at 22:56

3 Answers3

0

If the file really has all individual words on a new line (your output suggests something else) then the following should suffice:

var output = fs.readFileSync('../dictionary/dictionary.txt', 'utf8')
  .trim() // to remove whitespace
  .split('\r')   // creates array with individual words
  .map(item => { return { word :item } }); // creates array with objects
return output[randNum % output.length].word;

No need to do reduce or create another outobject.

This code should work with valid input, where words are separated by '\r'. The output suggest words are separated by '\r\n' or '\r\'. This creates words with '\r'. If you want words without '\r', you should apply some regex to flush that out. Maybe change into .split(/\r\n|\r|\n/g); will do the trick.

PS: the % part is to ensure that if randNum input is larger than the array length, you do not get error output. Array is created inside the function, so when called, it is still unclear what the maximum valid number actually will be.

wintvelt
  • 13,855
  • 3
  • 38
  • 43
  • tried your code and it is just throwing an error of "cannot read property of word of undefined" –  Oct 28 '15 at 22:58
  • I suspect it breaks down at the start because of the input file. What is the output if you `console.log(fs.readFileSync('../dictionary/dictionary.txt', 'utf8'))` ? – wintvelt Oct 28 '15 at 23:00
  • returns the text in the file, on new lines as it reads if I opened it in txt format –  Oct 28 '15 at 23:04
  • OK, small steps..so what does `console.log(fs.readFileSync('../dictionary/dictionary.txt', 'utf8')).trim()` output? – wintvelt Oct 28 '15 at 23:07
  • the same, all trim does is remove excess whitespace if any. –  Oct 28 '15 at 23:08
  • OK, next: what does `console.log(fs.readFileSync('../dictionary/dictionary.txt', 'utf8')).split['\r']` output? – wintvelt Oct 28 '15 at 23:09
  • it looks for the \r special char in the file and splits the file between each, thus each word on each line becomes an array property –  Oct 28 '15 at 23:11
  • Have you actually tested this? [Here](http://stackoverflow.com/questions/1155678/javascript-string-newline-character) I found that it should actually be more like `.split(/\r\n|\r|\n/g);` – wintvelt Oct 28 '15 at 23:15
  • same result, mostly because there are no single \r or \n chars, its always \r\n at the end of the lines and so that is why I have ti set as \r\n only at the moment –  Oct 28 '15 at 23:20
  • Hmm, does `console.log(output[1]);`(before your return statement) give you any sensible output? Expect `{ word : '' }` Perhaps you could update your question with latest version of your code? Or share fiddle? (can look at it again tomorrow) – wintvelt Oct 28 '15 at 23:35
0

One solution possible :

var str = " line_0\r\nline_1\r\nline_2\r\nline_3\r\nline_4\r\nline_5\r\nline_6\r\nline_7\r\nline_8\r\nline_9\r\nline_10\r\nline_11\r\nline_12\r\nline_13\r\nline_14\r\nline_15\r\nline_16\r\nline_17\r\nline_18\r\nline_19\r\nline_20\r\nline_21\r\nline_22\r\nline_23\r\nline_24\r\nline_25\r\nline_26\r\nline_27\r\nline_28\r\nline_29\r\nline_30\r\nline_31\r\nline_32\r\nline_33\r\nline_34\r\nline_35\r\nline_36\r\nline_37\r\nline_38\r\nline_39\r\nline_40\r\nline_41\r\nline_42\r\nline_43\r\nline_44\r\nline_45\r\nline_46\r\nline_47\r\nline_48\r\nline_49\r\nline_50\r\nline_51\r\nline_52\r\nline_53\r\nline_54\r\nline_55\r\nline_56\r\nline_57\r\nline_58\r\nline_59\r\nline_60\r\nline_61\r\nline_62\r\nline_63\r\nline_64\r\nline_65\r\nline_66\r\nline_67\r\nline_68\r\nline_69\r\nline_70\r\nline_71\r\nline_72\r\nline_73\r\nline_74\r\nline_75\r\nline_76\r\nline_77\r\nline_78\r\nline_79\r\nline_80\r\nline_81\r\nline_82\r\nline_83\r\nline_84\r\nline_85\r\nline_86\r\nline_87\r\nline_88\r\nline_89\r\nline_90\r\nline_91\r\nline_92\r\nline_93\r\nline_94\r\nline_95\r\nline_96\r\nline_97\r\nline_98\r\nline_99 ";

var arr = str
           .trim()
           .split("\r\n")
           .map(function(value , index){
             return { index: index , word : value}; 
           });


var len = arr.length;
var randNum = Math.floor(Math.random() * len);

var result = arr[ randNum ].word;

document.body.innerHTML+= '<br> randNum = ' + randNum + ' result : ' + result ;
Just click run again and again . . .

So your code become :

var fs = require('fs),
    getWordFromRandomNumber = function(randNum) {
        var output = fs.readFileSync('../dictionary/dictionary.txt', 'utf8')
           .trim()
           .split('\r\n')
           .map( val => { return {  word : val }; });

       console.log(JSON.stringify(output, null, 2));
       return output[ randNum ].word;
   };

getWordFromRandomNumber(25);

Note that each time you call getWordFromRandomNumber you will read the dictionary file , split it , map it !
If your dictionary is static maybe you can 'cache' the result of process !

var fs = require('fs),
    cached = null ,
    getWordFromRandomNumber = function(randNum) {

       if(cached) return cached[ randNum ].word;

       var output = fs.readFileSync('../dictionary/dictionary.txt', 'utf8')
           .trim()
           .split('\r\n')
           .map( val => { return {  word : val }; });

       console.log(JSON.stringify(output, null, 2));
       cached = output;
       return output[ randNum ].word;
   };

getWordFromRandomNumber(25);
Anonymous0day
  • 3,012
  • 1
  • 14
  • 16
0

I have my application working perfect now, the issue was fixed by using ajax instead of nodes fs.

Now I have this:

var getDictionaryFile = function(file) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", file, false);
    xhr.send(null);
    var returnValue = xhr.responseText;
    return returnValue;
},
getWordFromRandomNumber = function(randNum, el) {  
        var target = document.querySelectorAll(el),
            output = getDictionaryFile("../dictionary/dictionary.txt")
        .trim()
        .split('\r\n');

        [].forEach.call(output, function(line) {
            if(output[randNum % output.length - 1] == line ){
                [].forEach.call(target, function(element) {
                    element.innerHTML = line;
                });
            }
        });

    }

And the response text is doing the same thing as the last code except working, ie: being read, split into an array, looped over and then the index I want is decided by a random number. Thus, I get a random word with each request as expected.

  • Are you using Node server-side ??? i don't understand why you decide to put this part on client side ! – Anonymous0day Oct 29 '15 at 01:19
  • this is pureJS, no node in this answer. What are you on about? –  Oct 30 '15 at 15:35
  • pureJS meaning pure javascript, ie: no frameworks, plain, simple JS only. –  Oct 30 '15 at 15:36
  • When i told Node i was talking about Node.js ! ! server-side ! you have put the tag [[node.js]], you use `var fs = require('fs')` and at last you talk about ajax, so i don't understand ! ?? – Anonymous0day Oct 30 '15 at 22:00
  • My original questions had an issue. At the time of the question I used node. Then I fixed my issue by using `XHR` instead of `fs`. and altering what is returned by the `getRandomWordFromNumber` function. –  Oct 31 '15 at 12:46