I am trying to write javascript code that allows me to extract which words (given as a list) contain either 1 or more characters in a given list of words.
function filterWords(words, letters) {
var myArrayOfLetters = Array.from(letters)
var output;
for(var i = 0; i<myArrayOfLetters.length; ++i)
{
output = words.filter(word => word.includes(myArrayOfLetters[i]))
}
return output;
}
This is the code I have so far but it is not working.
This is an example of the input and the output required:
words = ['the','dog','got','a','bone']
letters = 'ae'
output = ['the','a','bone']
As you can see the output contains all the words that have either 'a' or 'e' in them or both.
How would I go about solving this issue?
You're on the right track, but you have your loops backward. You want to use the filter as the outer loop, and the loop over the array of letters as the inner loop, since you want to know if a word has any of those letters in it. The inner loop can be a call to the some method rather than an explicit loop:
function filterWords(words, letters) {
const myArrayOfLetters = Array.from(letters);
const output = words.filter((word) =>
myArrayOfLetters.some((letter) => word.includes(letter))
);
return output;
}
some returns true if the callback ever returns true (or any truthy value), or false if the callback never does.
Live Example:
function filterWords(words, letters) {
const myArrayOfLetters = Array.from(letters);
const output = words.filter((word) => myArrayOfLetters.some((letter) => word.includes(letter)));
return output;
}
const words = ["the", "dog", "got", "a", "bone"];
const letters = "ae";
console.log(filterWords(words, letters));
Here's an example with a word that has both a and e in it; note it's only included once:
function filterWords(words, letters) {
const myArrayOfLetters = Array.from(letters);
const output = words.filter((word) => myArrayOfLetters.some((letter) => word.includes(letter)));
return output;
}
const words = ["the", "dog", "got", "a", "really", "nice", "bone"];
const letters = "ae";
console.log(filterWords(words, letters));
You can simply achieve it with the help of Array.filter() along with Array.some() method.
Live Demo :
let words = ['the', 'dog', 'got', 'a', 'bone'];
const letters = 'ae';
const splittedLetters = letters.split('');
const res = words.filter(item => {
return splittedLetters.some(word => item.includes(word));
});
console.log(res);
let words = ['javascript', 'java', 'ruby', 'python', 'php'];
let filterWords =(words, chars) => {
return words.filter(word => word.split('').some(char => chars.includes(char)));
}
console.log(filterWords(words, 'pa')); //['JavaScript', 'Java', 'Python', 'PHP']
Related
let array1 = ["?", "!", "."];
let array2 = ["live.", "ali!", "harp", "sharp%", "armstrong","yep?"];
console.log(array2.filter((x) => x.endsWith("?")));
The output is just: ['yep?']
Because the function endsWith() only checked for "?" as you see in the code.
How do I loop the elements on the array1 (suffixes) inside the endsWith function so the output is:
['live.', 'ali!', 'yep?']
You could use a regex, and then match each element in the filter iteration against it.
/[?!.]$/ says match one of these things in the group ([?!.]) before the string ends ($).
const arr = ['live.', 'ali!', 'harp', 'sharp%', 'armstrong', 'yep?'];
const re = /[?!.]$/;
const out = arr.filter(el => el.match(re));
console.log(out);
Regarding your comment you can pass in a joined array to the RegExp constructor using a template string.
const query = ['.', '?', '!'];
const re = new RegExp(`[${query.join('')}]$`);
const arr = ['live.', 'ali!', 'harp', 'sharp%', 'armstrong', 'yep?'];
const out = arr.filter(el => el.match(re));
console.log(out);
You can use an inner .some() call to loop over your array1 and return true from that when you find a match instead of hardcoding the ?:
const array1 = ["?", "!", "."];
const array2 = ["live.", "ali!", "harp", "sharp%", "armstrong","yep?"];
const res = array2.filter((x) => array1.some(punc => x.endsWith(punc)));
console.log(res);
Above, when you return true (or a truthy value) from the .some() callback, the .some() method will return true, otherwise it will return false if you never return true, thus discarding it.
My main objective is to check if the string contains array of words.
If the string contain $ in front of a word, I don't want it to check the string for array of words and want to straight way console.log it.
The problem I'm having is that its not checking for "Exact words".
For example if you put E, the text should show up since, there's no words that contains only 'E' however, its not showing up.
For instance:
const res = `EU, U.S. REACH DEAL TO RESOLVE BOEING-AIRBUS TRADE DISPUTE
$BA`;
const filters = ["E", "OPEC", "Repo"];
if (!filters.some(element => res.includes(element))) {
console.log(res);
}
Another method, I was thinking maybe using the split method and to check for every array item whether it's a filtered word or not.
var res = `EU, U.S. REACH DEAL TO RESOLVE BOEING-AIRBUS TRADE DISPUTE $BA`;
var filters = ["E", "OPEC", "Repo"];
if (filters.some(element => new RegExp('\\b'+element + '\\b').test(res))) {
console.log(res);
}
Use ES6 Array.filter() and arrow functions with expression body:
var words = ['get', 'help', 'set', 'moon', 'class', 'code', 'Get', ];
var letter = 'e';
var word = "get";
const output = words.filter(x=>x.includes(letter));
console.log(output);
const output2 = words.filter(x => x.toLowerCase().includes(word));
console.log(output2);
.split() each string into an array of lower cased strings (delimiter is a space or a comma). If there's more than one string to be filtered, put them into an array
const strings = ['aaa, BBB, ccc', 'vhko nuu', 'String'];
let arrArr = strings.map(str => {
return str.toLowerCase().split(/[,\s]/);
});
// arrArr = [['aaa', 'bbb', 'ccc'], ['vhko', 'nuu'], ['string']]
Then run each string array of arrArr (array of arrays) through .flatMap((strArr, idx)... and each string of each strArr (string array) through .flatMap(str...
return arrArr.flatMap((strArr, idx) => {
return strArr.flatMap(str => {...
For each str (string) use .includes(list) and .startsWith(char) in a ternary to test if str is in the list or if it starts with a specific string (if the third parameter char was passed).
<IF> list.includes(str) ? <TRUE|THEN> [strings[idx]]
: <ELSE IF> char && str.startsWith(char) ? <TRUE|THEN> [strings[idx]]
: <ELSE|THEN> [];
const strs = [
`EU, U.S. REACH DEAL TO RESOLVE BOEING-AIRBUS TRADE DISPUTE $BA`,
`a, b, C, d, E, f`,
`OPEC reaches agreement`,
`This has opec., repo#, and a dollar$ so this should be ignored`
];
const words = ["e", "opec", "repo"];
const wordFilter = (list, strings, char) => {
let arrArr = strings.map(str => {
return str.toLowerCase().split(/[,\s]/);
});
return arrArr.flatMap((strArr, idx) => {
return strArr.flatMap(str => {
return list.includes(str) ? [strings[idx]] :
char && str.startsWith(char) ? [strings[idx]] :
[];
});
});
};
console.log(wordFilter(words, strs, '$'));
I think you can get some idea from this example.click here to see jsFiddle
var words = ['get', 'help', 'set', 'moon', 'class', 'code'];
var letter = 'e';
function find(words, letter) {
letter = letter.split(''); //get it to as object the we can use it in every method as follwing
return words.filter(function(word) { //get pne buy one word in words array
return letter.every(function(char) {
return word.includes(char); // return word including the letter that you request
});
});
}
const output = find(words, letter);
console.log(output);
I have an array called Symbols, it gets strings found by a regular expression pushed into it.
I now need to sort through the array and find out if there is a string that has every letter capitalized in it. I have tried similar things in the classified function below everything has returned "false" thus far, even if there is an element that is just "AAAA"
let symbols = [];
let regr = RegExp(/{\$([^\$]+)\$}/, 'g')
function genToken(inStream){
let array;
let vrtStream = inStream.trim();
console.log("Extracting meaningful symbols from string: ", vrtStream);
while((array = regr.exec(vrtStream)) !== null){
console.log(`Meaningful symbol: ${array[0]} found and assigned. Next starts at ${regr.lastIndex}.`)
symbols.push(array)
}
if(symbols.length > 0){
for(index = 0; index < symbols.length; index++){
symbols[index].splice(0, 1);
console.log(`${symbols[index].length} meaningful symbols currently indexed.`);
console.log(symbols);
}// end for
return classify(symbols);
} else {
console.log("no elements in array");
}
function classify(data, index){
console.log("Classify called", symbols)
//symbols is data
symbols.forEach(function(item, index, array){
if(item.toUpperCase == true){
console.log(`${item} is upper`)
} else {
console.log('false');
}
})
}
}
If you need to know which items in an array are all caps, you can map over them and use the regexp test method:
const arr = ['aaa', 'aAa', 'AAa', 'AAA', 'AAAa'];
const allCaps = arr.map(el => /^[A-Z]+$/.test(el));
console.log(allCaps);
If you just need to find the first one, or filter to only include the ones that match, you can use the find or filter array methods:
const arr = ['aaa', 'aAa', 'AAa', 'AAA', 'AAAa', 'BBBB'];
const first = arr.find(el => /^[A-Z]+$/.test(el));
console.log(first);
const all = arr.filter(el => /^[A-Z]+$/.test(el));
console.log(all);
Easy way to check if string is all uppercase is create uppercase string from it and then check if it is same as old string
// just some dummy data
const array = ["some data", "AAAA", "AAaA", "AAAAAB", "ALL_CAPS"];
// actual code to check if string is all uppercase
const allCapsArray = array.filter((str) => str.toUpperCase() === str);
// just printing output
console.log(allCapsArray);
For search purposes, given a string like BBC Sport I want to construct an array that looks like:
[ 'BBC', 'BB', 'B', 'Sport', 'Spor', 'Spo', 'Sp', 'S' ]
I've implenented it using 2 for loops:
const s = "BBC sport";
const tags = [];
const words = s.split(" ");
for (let word of words) {
const wl = word.length;
for (let i = 0; i < wl; i++) {
tags.push(word.substr(0, wl - i));
}
}
// tags now equals [ 'BBC', 'BB', 'B', 'Sport', 'Spor', 'Spo', 'Sp', 'S' ]
However, I'd like to implement it, if possible, with the reduce function instead of for loops.
How would you solve it?
Honestly I'd write the code the way you did. Two loops are readable, maintainable and fast.
If you really need a oneliner:
s.split(" ").flatMap(word => Array.from(word, (_, i) => word.slice(0, i + 1)))
Here is a solution relying on function generators (which I would use) and a solution with reduce (as you asked) (which I wouldn't personally use), accepting an input string and a separator.
In your case, the separator is blankspace, of course, but it can be customized.
The below code will iterate through the input string and slice the relevant part of the string for each occurrence, by capitalizing it (since it looks like you are).
This should be elastic enough and, at the same time, easy to customize by eventually adding additional parameters to the toTagList method, or allowing further transformations since it's iterable.
const s = "BBC sport";
function* toTagList(input, separator) {
// split by the separator.
for (const block of input.split(separator)) {
// For each string block, split the whole word.
var splitted = block.split('');
// slice the input array by taking from the first character to the last one, then decrease to get only the previous portions of said word.
for (var i = splitted.length; i > 0; i--) {
// Finally, yield the capitalized string.
yield capitalize(splitted.slice(0, i).join(''));
}
}
}
// this just capitalizes the string.
function capitalize(input) {
return input.charAt(0).toUpperCase() + input.substring(1, input.length);
}
console.log([...toTagList(s, ' ')]);
If you really want to do that with reduce:
const s = "BBC sport";
const tags = s.split(' ').reduce((acc, next) => {
return acc.push(...Array.from({length: next.length}).map((_, i) => {
return (next.split('').slice(0, i + 1)).join('')
})), acc;
}, [])
console.log(tags);
I am trying to filter some data from an array in a JSON file, based on an input of the form string1, string1,string2, string1,string2,string3 etc., that is, some strings separated by a ,.
What I'm trying to do:
let arrInput = document.getElementById('inputBox').val.split(',');
for(let i = 0; i < arrToFilter.length; i++){
if(.........what to write here?...........){
arrOutput.push(arrToFilter[i]);
}
}
return arrOutput;
If the arrInput had a fixed length, I could accomplish this using indexOf != -1 for each element in arrInput, but here, since the length of arrInput is variable, how can I check if at least one of the strings present in arrInput is also present as a substring in arrToFIlter[i]?
Edit:
Example:
Let arrToFilter be ["abcqwer", "pizza", "definition", "abcdef", "example"]
Case 1 :
Say the input entered (in an <input> element) is abc,def.
For this, the arrOutput should be ["abcqwer", "definition", "abcdef"]
Case 2:
Say the input entered is abc
Expected output : ["abcqwer", "abcdef"]
Simple way is using some and filter,
var string = 'ad,kk,sb';
var array = ['adik', 'klop', 'pp'];
var stringers = string.split(',');
var result = array.filter((arr) => {
var isPresent = stringers.some(stringer => arr.includes(stringer));
return isPresent ? true : false;
});
console.log(result);
You need to iterate both arrays
let arrToFilter = ['abcqwer', 'pizza', 'definition', 'abcdef', 'example'];
let arrOutput = [];
let arrInput = document.getElementById('inputBox').value.split(',');
arrToFilter.forEach(filter => {
arrInput.forEach(input => {
if (!!input && filter.includes(input)) {
arrOutput.push(filter);
}
});
});
// distinct the output
return arrOutput.filter((v, i, a) => i === a.indexOf(v));