I want to get length of every element in array
my code is
var a = "Hello world" ;
var chars = a.split(' ');
so I will have an array of
chars = ['Hello' , 'world'] ;
but how I can get length of each word like this ?
Hello = 5
world = 5
You can use map Array function:
var lengths = chars.map(function(word){
return word.length
})
ES6 is now widely available (2019-10-03) so for completeness — you can use the arrow operator with .map()
var words = [ "Hello", "World", "I", "am", "here" ];
words.map(w => w.length);
> Array [ 5, 5, 1, 2, 4 ]
or, very succinctly
"Hello World I am here".split(' ').map(w => w.length)
> Array [ 5, 5, 1, 2, 4 ]
The key here is to use .length property of a string:
for (var i=0;i<chars.length;i++){
console.log(chars[i].length);
}
You could create a results object (so you have the key, "hello", and the length, 5):
function getLengthOfWords(str) {
var results = {};
var chars = str.split(' ');
chars.forEach(function(item) {
results[item] = item.length;
});
return results;
}
getLengthOfWords("Hello world"); // {'hello': 5, 'world': 5}
Try map()
var words = ['Hello', 'world'];
var lengths = words.map(function(word) {
return word + ' = ' + word.length;
});
console.log(lengths);
You can use forEach, if you want to keep the words, and the length you can do it like this:
var a = "Hello world" ;
var chars = a.split(' ');
var words = [];
chars.forEach(function(str) {
words.push([str, str.length]);
});
You can then access both the size and the word in the array.
Optionally you could have a little POJO object, for easier access:
var a = "Hello world" ;
var chars = a.split(' ');
var words = [];
chars.forEach(function(str) {
words.push({word: str, length: str.length});
});
Then you can access them like:
console.log(words[0].length); //5
console.log(words[0].word); //"Hello"
Or using map to get the same POJO:
var words = chars.map(function(str) {
return {word: str, length: str.length};
});
Related
I want to determine if string has at least 2 same elements from the array
const array = ["!", "?"];
const string1 = "!hello"; // should return false
const string2 = "!hello?"; // should return false
const string3 = "!hello!"; // should return true
const string4 = "hello ??"; // should return true
const string5 = "hello ?test? foo"; // should return true
const string6 = "hello ?test ?? foo"; // should return true
I'm not sure what is gonna be better: a regex or a function? Any would be fine.
I tried this:
const array = ["!", "?"];
const string = "test!";
array.every(ar => !string.includes(ar));
But it only detects if there at least 1 elements from array, not 2.
You can use Array#some and String#split to do it:
const check=(array,string)=>array.some(char=>(string.split(char).length-1)>=2)
const array = ["!", "?"];
console.log(check(array,"!hello"))
console.log(check(array,"!hello?"))
console.log(check(array,"!hello!"))
console.log(check(array,"hello ??"))
console.log(check(array,"hello ?test? foo"))
console.log(check(array, "hello ?test ?? foo"))
How does it work?
Let's split up (I mean to split() up)!
const check=(array,string)=>
array.some(char=>
(
string.split(char)
.length-1
)>=2
)
First, use Array#some, which tests that at least one element of the array should pass (i.e. either ? or !)
Split up the string by char, and count how many parts do we have
If we have n parts, it means that we have n-1 places where the char matches. (e.g. 2 | splits a string into 3 parts: a|b|c)
Finally, test whether we have 2 or more delimiters
Another way is to use a pattern with a capturing group and a dynamically created character class for [!?] and a backreference \1 to what is captured in group 1 to make sure there are 2 of the same characters present.
([!?]).*\1
Regex demo
For example
const array = ["!", "?"];
const regex = new RegExp("([" + array.join(("")) + "]).*\\1");
[
"!hello",
"!hello?",
"!hello!",
"hello ??",
"hello ?test? foo",
"hello ?test ?? foo"
].forEach(str => console.log(str + ": " + regex.test(str)));
You can use string split and array length like:
const array = ["!", "?"];
const string6 = "hello ?test ?? foo";
var len1 = string6.split(array[0]).length;
var len2 = string6.split(array[1]).length;
if (len>2)||(len2>2)
return true;
EDIT: Using for loop
for (let i=0;i<array.length;i++){
var len = string6.split(array[i]).length;
if (len>2)
return true;
}
return false;
You can follow a very simple solution like below. Split the string using the character in array. check the left of the split operation. If the length is minimum 2, then return true, else false.
Here is a sample jsFiddle: https://jsfiddle.net/sagarag05/qk8f2Lz7/
const array = ["!", "?"];
var str = "How are you!! doing !today?";
function isFound(arr, str){
var isPresent = false;
for(var i=0; i < arr.length; i++){
var res = str.split(arr[i]);
if(res.length-1 >= 2){
isPresent = true;
break;
}
}
return isPresent;
}
isFound(array, str);
Create a function which can be handy for n number of occurrences to find
const arrayData = ["!", "?"];
const strData = "test!";
function checkElements(arr, str, occNum) {
var ctr = 0;
arr.forEach(function (elem) { if(str.includes(elem)) ctr++});
return ctr >= occNum
}
checkElements(arrayData, strData, 2)
Use loop over array and count occurrence then check if occurrence is greater than 1.
function has2(string1, array)
{
for(let i=0;i<array.length;i++)
{
if (string1.split('').reduce(function(n, val) {
return n + (val === array[i]);
}, 0) > 1)
{
return true;
}
}
return false;
}
console.log(has2("!hello!", ["!", "?"])); // true
console.log(has2("!hello?", ["!", "?"])); // false
Here is a regex trick approach. We can try removing all characters from the input which are not part of the character class of characters to find. Then, assert that there are at least two distinct characters remaining in the input.
var input = "!hello?";
input = input.replace(/[^!?]+/g, "");
if (/(.).*(?!\1)./.test(input)) {
console.log("MATCH");
}
else {
console.log("NO MATCH");
}
The logic here is fairly straightforward. Using the input !hello? as an example, we first remove all non marker characters, leaving us with !?. Then, we use a regex to assert that there are at least two distinct characters remaining. This is true for this input, so we print MATCH.
Edit:
To build the regex alternation from your input array use join:
const array = ["!", "?"];
var regex = "[^" + array.join("") + "]+";
There is a much simpler solution for this:
var a = ["!", "?"], s = "!hello!";
a.some(v=>s.split(v).length>2) // (returns true if multiples are found)
We can turn it into a function to test:
const a = ["!", "?"];
function Test(s) { return a.some(v => s.split(v).length > 2) }
const string1 = "!hello"; // should return false
const string2 = "!hello?"; // should return false
const string3 = "!hello!"; // should return true
const string4 = "hello ??"; // should return true
const string5 = "hello ?test? foo"; // should return true
const string6 = "hello ?test ?? foo"; // should return true
console.log(Test(string1), Test(string2), Test(string3), Test(string4),
Test(string5), Test(string6));
> false false true true true true
Note: My code changed a few times and in the end was close to the accepted answer and I didn't realize. That said, you don't need to subtract anything, so that part is unnecessary.
function checkDups(arr, str) {
var ctr = [];
for (var i = 0; i < arr.length; i++) {
var pos = str.indexOf(arr[i]);
var count = 0;
ctr[i] = 0;
while (pos > -1) {
++count;
pos = str.indexOf(arr[i], ++pos);
}
if (count >= 2) {
return true
}
}
return false
}
console.log(checkDups(["!", "?"], "!hello"))
console.log(checkDups(["!", "?"], "!hello?"))
console.log(checkDups(["!", "?"], "!hello!"))
console.log(checkDups(["!", "?"], "hello ??"))
console.log(checkDups(["!", "?"], "hello ?test? foo"))
console.log(checkDups(["!", "?"], "hello ?test ?? foo"))
I am hoping to place the letters of a string found in an array into subarrays using JavaScript.
For example:
var word = "abc def";
var wordArray = [];
var firstArray = randomWord.split(" ");
for (var l = 0, len = firstArray.length; l < len; l++) {
for (var m = 0, len2 = firstArray[l].length; m < len2; m++) {
console.log(firstArray[l][m]);
WordArray.push(firstArray[l][m]);
WordArray = randomWordArray.filter(function(str) {
return /\S/.test(str);
});
};
};
console.log("word", word);
console.log("wordArray", wordArray);
Currently, I get is ...
wordArray = ["a", "b", "c", "d", "e", "f"];
What I am hoping for is ...
wordArray = [["a", "b", "c"],["d", "e", "f"]];
I suppose the real questions is is this possible?
Thank you, in advance, for any and all suggestions.
You basically want to solve two problems. First, you want to create a separate array for each word (detect word boundaries). Next, you want to split each word into its component letters.
Doing this without any "modern" JavaScript magic (map, reduce, etc) would look something like this:
var word = "abc def";
// Step 1.
var wordArray = word.split(" ");
console.log(wordArray); // ["abc", "def"]
// Step 2.
for (var i = 0; i < wordArray.length; i++)
{
wordArray[i] = wordArray[i].split("");
}
console.log(wordArray); // [["a", "b", "c"], ["d", "e", "f"]]
This second step can be written in a slightly more compact form by realizing that this is what's known as a mapping problem. You want to take every element of the array and convert it from one form (a string) to another (an array of letters). For this, JavaScript provides the map method:
var squares = [1, 2, 3].map(function(x) { return x * x; });
console.log(squares); // [1, 4, 9]
So we can re-write step 2 using this method like so:
wordArray = wordArray.map(function(word) { return word.split(""); });
Finally, we can simplify further using an arrow function. Arrow functions basically are short-hand for the following:
x => x + 1;
// Is equivalent to:
(function(x) {
return x + 1;
}).bind(this);
Ignore the .bind() bit for now (it's unimportant for your problem) and we can write step 2 as:
wordArray = wordArray.map(word => word.split(""));
Combining these two improvements we get:
var word = "abc def";
// Step 1.
var wordArray = word.split(" ");
// Step 2.
wordArray = wordArray.map(word => word.split(""));
We can shrink this slightly more by passing the result of word.split(" ") directly to step 2 without storing it into an intermediate variable:
var word = "abc def";
// Step 1 and 2.
var wordArray = word.split(" ").map(word => word.split(""));
And there you have it. The "modern" answer, created from the basics.
Here is what I would do:
1) Split the words by spaces ''
2) Use the spread syntax to expand each word within the above array.
const word = "abc def";
const res = word.split(' ').map(element => [...element]);
console.log(res)
Split the words by space, and then map and split each word:
const words = "abc def";
const result = words.split(' ')
.map(w => w.split(''));
console.log(result);
I think, This code will help you!
var data = "this is test data";
var arrayData = data.split(' ').map(i=> i.split(''));
console.log(arrayData);
First split the text to words using the space,
Then after getting each word, use the empty string to split by letter
This should work
let text = "abc def";
let arrayFinal = [];
for(let word of text.split(' ')) {
let letterArray = [];
for(let letter of word.split('')) {
letterArray.push(letter);
}
arrayFinal.push(letterArray);
}
refere this
no need to perform nested loop manually, just use split and map to get the result
var word = "abc def";
var wordArray = word.split(" ").map(w => w.split(''));
I am sorry for my english.
var r=/([a-z]*)[a]{1}([a-z]*)/igm;
var s="araba";
The result I need,
a raba index:0
ar a ba index:2
arab a index:4
How can I do that with regexp ?
A single regular expression call will not be possible as regular expressions can't go back after they match something. You'll have to make a regex that will look for the character set you want (in your example [a]) and stop at every match, generating a new result and pushing it into an array (or use it directly). RegExp.prototype.exec is needed like this:
function mySplit(str, charList) {
// regex will match any character provided in the charList string (no need for {1} as it is the default)
var regex = new RegExp("[" + charList + "]", "g");
// the result array, will contain object indecating where the match was found and the parts
var result = [];
// before starting, execute the regex on the string str
regex.exec(str);
// using do-while to guarantee that there will be at least one result in the result array
do {
// the index of this match
var index = regex.lastIndex - 1;
// the result object for this match
var r = {
index: index, // the index
parts: [] // the parts (for example "a", "raba" ...)
};
var p;
// PREFIX PART
p = str.substr(0, index); // get the prefix
if(p.length) r.parts.push(p); // if not empty push it
// THE CHARACTER
p = str.substr(index, 1); // get it
if(p.length) r.parts.push(p); // if not empty push it (this is could be empty if nothing is matched)
// POSTFIX PART
p = str.substr(index + 1); // get it
if(p.length) r.parts.push(p); // push it if not empty
result.push(r); // push the object r as a result
} while(regex.exec(str));
return result;
}
console.log(mySplit("araba", "a"));
Note: the second parametter to mySplit could as much letters as you want. For example mySplit("araba", "ab"); will return this:
[
{
"index": 0,
"parts": [
"a",
"raba"
]
},
{
"index": 2,
"parts": [
"ar",
"a",
"ba"
]
},
{
"index": 3,
"parts": [
"ara",
"b",
"a"
]
},
{
"index": 4,
"parts": [
"arab",
"a"
]
}
]
Thank you İbrahim :)
My extended solution :
String.prototype.matchAllCombinations=function(regex,includeIndex,constGroups){
var str=this;
var includeIndex=includeIndex||false;
var constGroups=constGroups||[];
var newRegex;
if(constGroups.length==0){
var groups=regex.source.split(new RegExp('([(]{1}[^()]+[)]{1})','g'));
var newSource='';
for(var el,it=1,lim=groups.length-1;it<lim;it++){
el=groups[it];
if(el.charAt(0)!='('){
newSource+='('+el+')';
constGroups.push(it-1);
}else{
newSource+=el;
}
}
newRegex=new RegExp(newSource,'');
}else{
newRegex=regex;
}
var testStr=str;
var combinations=new Array();
var matches=new Array();
var combination=new Array();
var end=new String();
var k=new Number();
var constValues=new Array();
var itCount=new Number();
var lastTestStr=new String();
while((matches=testStr.match(newRegex))!=null){
k=2;
correct=true;
combination=new Array();
combination=matches.slice(1,matches.length);
if(combination[combination.length-1]!=""){
k=1;
}
combination[combination.length-k]+=end;
end=combination[combination.length-k];
if(itCount==0){
for(var it=0;it<constGroups.length;it++){
constValues.push(combination[constGroups[it]]);
}
}
testStr=combination.slice(0,combination.length-k).join('');
if(lastTestStr==testStr){
combinations=[];
break;
}
for(var it=0;it<constGroups.length;it++){
correct&=(combination[constGroups[it]].length==constValues[it].length);
}
if(correct){
if(includeIndex){
combination["indexes"]=new Array();
for(var it=0;it<constGroups.length;it++){
combination["indexes"].push(combination.slice(0,constGroups[it]).join('').length);
}
}
combinations.push(combination);
}
lastTestStr=testStr;
itCount++;
}
return combinations;
}
console.log('araba'.matchAllCombinations(new RegExp('([a-z]*)[a]{1}([a-z]*)'),true));
console.log('araba'.matchAllCombinations(new RegExp('([a-z]*)[a]{1}([a-z]*)[a]{1}([a-z]*)'),true));
console.log('araba'.matchAllCombinations(new RegExp('([a-z]*)[a]{1}([a-z]*)[a]{1}([a-z]*)[a]{1}([a-z]*)'),true));
console.log('araba'.matchAllCombinations(new RegExp('([a-z]*)[a]{1}([a-z]*)[a]{1}([a-z]*)[a]{1}([a-z]*)[a]{1}([a-z]*)'),true));
console.log('araba'.matchAllCombinations(new RegExp('([a-z]*)[p]{1}([a-z]*)'),true));
console.log('erebe'.matchAllCombinations(new RegExp('([a-z]*)([a]{1}|[e]{1})([a-z]*)'),true,[1]));
Given an array of words, write a function that returns an array of the words that occur an even number of times.
function even(["hello", "hi", "hello", "elephant", "hi"]);
That output should be:
["hello", "hi"]
This has been a toy problem I have been struggling with recently. I have solved similar problems counting and returning the number of occurrences of elements in an array but am having trouble taking that logic and applying it to this problem.
This is what I have tried so far, but have hit a wall when trying to output just the even occurrences:
function even(collection) {
var results = [];
for(var i = 0; i < collection.length; i++){
var value = collection[i];
if(results[value]){
results[value] = results[value] + 1;
}else{
results[value] = 1;
}
}
return results;
}
You can use reduce to get an actual count of the words, then simply return an array of the ones that have an even count:
function even(wordsArr) {
//Object of words and counts
var wordCounts = wordsArr.reduce(function(counts, word) {
if (!counts.hasOwnProperty(word)) {
counts[word] = 0;
}
counts[word]++;
return counts;
}, {});
//Now filter that out and return
return Object.keys(wordCounts).filter(function(word) {
return wordCounts[word] % 2 === 0
});
}
even(["hello", "hi", "hello", "elephant", "hi"]); //["hello", "hi"]
var arr = ["hello", "hi", "hello", "elephant", "hi"];
function onlyEvens( arr )
{
var countObj = {};
for( var i = 0; i < arr.length; i++ )
{
var item = arr[i];
if( countObj[ item ] !== undefined )
countObj[item]++;
else
countObj[item] = 1;
}//for()
var filteredArray = [];
for(var key in countObj )
{
if( countObj[key] % 2 == 0 )
filteredArray.push( key );
}
return filteredArray;
}//onlyEvens()
console.log( onlyEvens( arr ) );
Issues in your code:
you use collection instead of words
you cannot access array the associative way. You must declare it as object:
results[value]
you return result variable, but it is undeclared.
return result;
results only contains the occurrences of every word. There miss the code that calculates if the occurrences of a word are odd or even.
fixed code:
function even(words) { // <<< in your code was collection
var results = {};
for(var i = 0; i < words.length; i++){
var value = words[i];
if(results[value]){
results[value] = results[value] + 1;
}else{
results[value] = 1;
}
}
var ret = [];
for(var word in results)
if(results[word]%2 !== 0)
rest.push(word);
return ret;
}
function even(list) {
var d = list.reduce(function(d, w) { d[w] = !d[w]; return d; }, {});
return Object.keys(d).filter(function(w) { return !d[w]; });
}
console.log(even(["hello", "hi", "hello", "elephant", "hi"]));
console.log(even(["hello", "yo", "yo", "hi", "hello", "yo", "elephant", "hi"]));
Explanation: Use the array .reduce() method to create an object (d) with a property for each word (w) with a boolean value indicating whether the word has an odd number of occurrences. Then .filter() the keys to get all the ones that are not odd.
If you previously sort the array you can filter it as required in just a code line like this :
var even = (str) => str.sort().filter((element, index, arr) => index+1 === arr.lastIndexOf(element));
console.log(even(["hello", "hello", "hi", "elephant", "hi", "hi"])); //[ 'hello', 'hi' ]
I am trying to come up with a function that will take any string and output an array of numbers and strings without using .split(). Below are the tests it needs to pass and a function that passes the tests currently. I am curious about how other people would solve this.
function csvParse(inputString) {
var outputArray = [];
var inputArray = inputString.split(',');
for (var i =0; i < inputArray.length; i++) {
if (!Number.isNaN(+inputArray[i])) {
outputArray.push(+inputArray[i]);
} else {
outputArray.push(inputArray[i].replace(/['"]+/g,'').trim());
}
}
return outputArray;
};
describe('CSV Parse', function() {
it('should parse a string of integers correctly', function() {
var input = '3,7,9,1,25';
var output = [ 3, 7, 9, 1, 25 ];
expect(csvParse(input)).to.deep.equal(output);
});
it('should parse a string of strings correctly', function() {
var input = '"3","7","9","1","25"';
var output = ["3", "7", "9", "1", "25"];
expect(csvParse(input)).to.deep.equal(output);
});
it('should parse a string of integers and strings correctly', function() {
var input = '1, "one", 2, "two", 3, "three"';
var output = [1, "one", 2, "two", 3, "three"];
expect(csvParse(input)).to.deep.equal(output);
});
});
Basic JS solution just replacing the split method as you asked (fiddle here)
function dumbComaSplit(inputString) {
var strArray = [];
var tmpStr = "";
for (var i = 0; i < inputString.length; i++) {
if (inputString.charAt(i) == ',') {
strArray.push(tmpStr);
tmpStr = "";
continue;
}
tmpStr += inputString.charAt(i);
}
strArray.push(tmpStr);
return strArray;
};
function csvParse(inputString) {
var outputArray = [];
var inputArray = dumbComaSplit(inputString);
for (var i =0; i < inputArray.length; i++) {
if (!Number.isNaN(+inputArray[i])) {
outputArray.push(+inputArray[i]);
} else {
outputArray.push(inputArray[i].replace(/['"]+/g,'').trim());
}
}
return outputArray;
};
If you really really want to parse CSV format without spilt, here is one way you can do it using new ECMAScript 6 Template Strings feature.
The basic is that we replace CSV , with mock ${b} expressions and convert the string to a Template String. Then evaluate it while using tag feature. This will create the array for us.
Here is the fiddle.
function csvParse(inputString) {
b = null; //dummy variable
//Prepare the notation to be a TemplateString. Use var b in a dummy expression
inputString = "`" + inputString.replace(/,/g, '${b}') + "`";
//Evaluate. Note that we use a tag function inside the evaluation to create the array
//We also pass the string as a Template String to evaluate. This is optional
fn = new Function(`function tag(inputArray) {
return inputArray;
}
return tag ${inputString} `);
//Return the array
return fn().raw;
};
console.log(csvParse("power,of,es6"));
split is the way to go. But this is the answer you are looking for.