Getting only the match, instead of whole entry - javascript

With help of this thread I got the following piece of code, which find all occurrences of words with at least 3 letters:
arr = ["ab", "abcdef", "ab test"]
var AcceptedItems = arr.filter(function(item) {
return item.match(/[a-zA-Z]{3,}/);
});
In my case that should be abcdef and test.
But instead of the occurrences only, it gets me the whole entry of the array. So instead of just test it gets me ab test.
How can I get only the match (test), not the whole array entry.

.filter will keep an element if it matches the predicate you passed but you need to save a new value based on if that predicate is true. You could do this by first performing a map then a filter but I'd rather do this in one loop.
var AcceptedItems = [];
for (var i = 0, len = arr.length; i < len; i++) {
var match = arr[i].match(/[a-zA-Z]{3,}/);
if (match) {
AcceptedItems.push(match[0]);
}
}

Related

Create a function which takes in a word and spells it out, by consecutively adding letters until the full word is completed

Create a function which takes in a word and spells it out, by consecutively adding letters until the full word is completed.
This is my code for the solution. I am super new to JS. Could someone tell me the problem? Thank you.
function spelling(str) {
var str1 = [...str]
var n
str1.index[n] = str.slice(0, n+1)
return str1
}
Expected output:
Test.assertSimilar(spelling("bee"), ['b', 'be', 'bee'])
Test.assertSimilar(spelling("cake"), ['c', 'ca', 'cak', 'cake'
Actual output:
TypeError: Cannot set property 'undefined' of undefined at spelling at
Object.handleError at ContextifyScript.Script.runInThisContext at
Object.exports.runInThisContext
First of all, you never initialized n.
In addition, what is str1.index? It does not exist. If you want to access a cell in an array you should use: array[i].
Moreover, after you defined n, you need to update it for every char.
What I did was to fix all of what I mentioned above, and I created an empty array, and for each char of str I'm pushing to the array a slice of str and update n (++n means to use n after increment it by 1).
function spelling(str) {
var str1 = [];
let n = 0;
for (c in str)
str1.push(str.slice(0, ++n));
return str1;
}
console.log(spelling('bee'));
function spelling(str) {
return str.split('').map((el,i)=>str.slice(0,i+1));
}
Map can take a second parameter which is the index of the array that map is being called on.
You can use substring to achieve this.
The substring() method extracts the characters from a string, between
two specified indices, and returns the new sub string.
function spelling(str) {
let result = [];
for (let i = 1; i <= str.length; i++) {
result.push(str.substring(0, i));
}
return result;
}
console.log(spelling('bee'));
/**
* spelling("hello") // Returns ["h", "he", "hel", "hell", "hello"]
*/
function spelling(str) {
var arr = [];
var len = str.length;
while (len) {
arr.unshift(str.substring(0, len--));
}
return arr;
}

Finding a jumbled character sequence in minimum steps

There is a string consisting of all alphabets(a-z). I have to guess the jumbled sequence in minimum number of steps. After each guess, I will know if each of my character is in the right position or not.
I'm using the following approach:
Maintaining a list of indices of where each character can go
Generating a random sequence from above and updating the list on each response
Here's my code:
var validIDs = {};
function initialise() {
let indices = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
for(let i=0;i<26;i++) {
validIDs[String.fromCharCode(97+i)] = [...indices];
}
}
// response is a bool array[26]
// indicating the matching positions of pattern with the secret jumbled sequence.
function updateIDs(pattern, response) {
let index;
for(let i=0;i<pattern.length;i++) {
if(response[i]) {
validIDs[pattern[i]] = [i];
} else {
index = validIDs[pattern[i]].indexOf(i);
validIDs[pattern[i]].splice(index,1);
}
}
}
My validIDs is an object with [a-z] as keys and stores the possible positions of each character. Example: { a: [0, 1, 2], b: [3], ...and so on till 'z' }. The aim is to tighten the constraints on this object and finally arrive at the secret pattern.
I'm trying to create a valid pattern from this object without using brute force and would like to have some randomness as well. I wrote the following function to take a random index for each letter and create a sequence, but this fails if all the available indices of a letter are already taken.
function generateNewSequence() {
let sequence = [], result = [];
let rand, index = 0;
for(let letter of Object.keys(validIDs)) {
//Finding a random index for letter which is not already used
rand = Math.floor(Math.random()*validIDs[letter].length);
while(sequence.indexOf(validIDs[letter][rand]) !== -1) rand = Math.floor(Math.random()*validIDs[letter].length);
index = validIDs[letter][rand];
sequence.push(index);
result[index] = letter;
}
return result.join('');
}
Note: Another constraint is that the generated sequence should not contain any duplicates.

Why does my function return only one item that matches the criteria?

I am new to javascript and I am working on a coding challenge that requires you to build a function that takes an array of strings as an argument and returns all strings with four letters or characters. My function will return the first four-character item it finds, but then stops and will not return any more four-character items. The code is as follows:
function isFourLetters(arr) {
for (i=0; i < arr.length; i++) {
if (arr[i].length===4) {
return arr[i];
}
}
}
I stared at this for 10 minutes or so trying to see why the for-loop just stops once it reaches an array element with four characters, and for whatever reason I just cannot see it and it makes me think there is something about for-loops that I clearly don't understand. Any help would be greatly appreciated!
Your function is returning the first match (string with 4 letters).
You need to store those matches into an array
function isFourLetters(arr) {
for (i=0; i < arr.length; i++) {
if (arr[i].length===4) {
return arr[i]; // <--- Here your problem
}
}
}
An alternative is pushing the matches into an array:
function isFourLetters(arr) {
var matcher = [];
for (i=0; i < arr.length; i++) {
if (arr[i].length===4) {
matches.push(arr[i]);
}
}
return matches;
}
Or better, take a look at the function filter:
function isFourLetters(arr) {
return arr.filter(function(str) {
return str.length === 4;
});
}
you may declare a "tmpArr" and add 4-letter strings as the loop finds. then return the"tmpArr" at the end of the function.
The problem is that when you enter the if condition you do a return. The return breaks the function scope and returns only arr[i].
You should create a new array inside the function and then use the if to add elements on the returning array. Then, when the for loop ends you can return the whole new array.
You can user filter method in array.The filter() method creates a new array with all elements that pass the test implemented by the provided function.
var arr = ['1234','spray', 'limit',test', 'elite', 'exuberant', 'destruction', 'present'];
const result = arr.filter(arrElement => arrElement.length === 4);
console.log(result);
// Result : [1234,test]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

String.match.length returning array. Expected an integer value.

I am trying to write a function that counts the matches of a letter of the alphabet to letters in a string. I then store the count, per letter, into an associative array.
My problem is that string.match(regExpression) || [].length is returning an array. My expectation is it would return an integer value matching the length of the match. I know that the string.prototype.match() method returns an array, but my understanding (based on the formal description of the method) is that Sting.length returns a number.
What am I doing wrong?
function countLetters(string) {
//create array with letters of alphabet
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
var counts = [];
for (i = 0; i < alphabet.length; i++) {
var regExpression = new RegExp(alphabet[i], "g");
counts[alphabet[i]] = string.match(regExpression) || [].length
}
return counts;
}
I realize my mistake. The line string.match(regExpression) || [].length was behaving unexpectedly since I was missing parenthesis around the match method and logical operator before invoking the length method. As is I was returning the array OR the length of an empty array.
I also changed counts to an object.
Here's the fixed function:
function countLetters(string) {
//declare array with letters of alphabet
var alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
//declare object which will store our counts
var counts = {};
//iterate through alphabet array, find matches, and assign count of matches to counts object
for (i = 0; i < alphabet.length; i++) {
var regExpression = new RegExp(alphabet[i], "g");
counts[alphabet[i]] = (string.match(regExpression) || []).length
}
return counts;
}
You are not doing anything wrong but you are expecting the wrong value, in this case when string.match is right it will return an array which is the right behavior.
This method is used to retrieve the matches when matching a string against a regular expression, and those matched returned in an array

How to convert a string to an array based on values of another array in JavaScript

I have some data that I'm trying to clean up. For the field in question, I know what the possible values are, but the value is stored in a concatenated string and I need them in an array. Here is what I would like to do:
var valid_values = ['Foo', 'Bar', 'Baz'];
var raw_data = ['BarFoo','BazBar','FooBaz'];
desired_result = [['Bar','Foo'],['Baz','Bar'],['Foo','Baz']];
I'm not sure what this is called, so I hope this isn't a duplicate.
You can iterate over each data value, searching for allowed string with indexOf or contains and returning successful matches as array.
Here's my version of code and working example at jsFiddle:
var out = raw_data.map(function (raw) {
return valid_values.filter(function (value) {
return raw.contains(value);
});
});
//out === [['Bar','Foo'],['Baz','Bar'],['Foo','Baz']];
I assumed that output match order isn't important.
This is assuming some things about your data:
you need to split strings into 2-item pairs
input & terms are case-sensitive
you won't be dealing with null/non-conforming inputs (requires more edge-cases)
In that case, you'd want to do something like this:
// for each item in the desired result, see if it's a match
// at the beginning of the string,
// then split on the string version of the valid value
function transform(input){
for(i = 0; i < len; i++) {
if (input.indexOf(valid_values[i]) === 0) {
return [ valid_values[i], input.split(valid_values[i])[1] ];
}
}
return [];
}
// to run on your input
var j = 0, raw_len = raw_data.length, desired_result = [];
for(; j < raw_len; j++) {
desired_result.push(transform(raw_data[j]));
}
This code is pretty specific to the answer you asked though; It doesn't cover many edge cases.

Categories

Resources