The task is to convert a string into a type object:

  • property name is a word from a string,
  • property value is the number of entries in the string.

Wrote function:

function countWords(str) { var arr = str.split(' '); var obj = {}; for (var i = 0; i < arr.length; i++) { var word = arr[i]; obj[word] = str.split(word).length - 1; } return obj; } console.log(countWords('ask a bunch get a bunch')); // Результат --> {ask: 1, a: 3, bunch: 2, get: 1} // Ожидаемый результат --> {ask: 1, a: 2, bunch: 2, get: 1} 

How to ensure that 'a' from the word 'ask' is not considered the occurrence of the word 'a'?

I tried regular expressions, but I don’t understand how to attach '\ b' to the word variable in split (word).

  • and obj[word]++ you just can not do it because ...? - teran
  • @teran, because undefined. - Qwertiy
  • @Qwertiy thank you cap! :) I'm generally talking about the approach, not about specifics :) - teran
  • And / \\[ .... not? - PROPHESSOR
  • @teran, it never even occurred to me. My level is the most basic. thanks for the science! - easyNick

2 answers 2

Although a more elegant way is already given in the answer @Qwertiy I will leave this code as one of the options.

 function countWords(str) { var arr = str.split(' '); var obj = {}; for (var i = 0; i < arr.length; i++) { var word = arr[i]; if( !obj[word]) obj[word] = 1 else obj[word]++; } return obj; } console.log(countWords('ask a bunch get a bunch')); 

var obj = {} should be replaced by Object.create(null) , as written in the comments.

  • Run on the line from my answer and pay attention to toString: NaN . I’ve got protection from this in two places - Object.create(null) and ~~ - that is, even if you initially put {} , then ~~ still turns garbage into 0. Well, no one has more than 2 million words anyway will not give :) - Qwertiy
  • @Qwertiy yes, toString saw - teran
  • Another option !obj[word] replaced by !obj.hasOwnProperty(word) - it will be somewhat friendlier for the old Jeshek)) - Qwertiy
  • @teran, thanks, your answer is clearer to me - I can at least repeat it on occasion. In order to assimilate the answer to Qwertiy, I still need to learn a little. - easyNick

 function count(s) { var a = s.split(/[^a-zа-яё]+/ig).filter(Boolean) var res = Object.create(null) for (var q=0; q<a.length; ++q) { res[a[q]] = ~~res[a[q]] + 1 } return res } console.log(count("Just a test with toString and русский текст, test again and текст again!")) 
 .as-console-wrapper.as-console-wrapper { max-height: 100vh; } 

What's so interesting:

  • delimiters are everything except Russian and Latin letters.
  • .filter(Boolean) deselects blank lines if there are delimiters at the beginning or end of a line
  • Object.create(null) creates a clean object that has nothing in the prototype, including methods like toString
  • ~~res[a[q]] results in non- Object.create(null) garbage to 0 - in this case it is necessary for undefined, but if you replace Object.create(null) with {} , it will also help with toString , since this is not a number. Of the minuses - a limit of 2 31 -1, but so many words in the line will not.
  • ~~res[a[q]] + 1 - what is this (~~) magic? - MedvedevDev
  • @teran, thank you. - MedvedevDev
  • @MedvedevDev, added a little. - Qwertiy