Looping through arrays to check for patterns - javascript

I'm trying to loop through an array to check for a specific pattern but keep getting no output afterwards. Not sure what I've done wrong! I would appreciate any help!
I am testing for the pattern at or hat.
sample = ["cat fat hat mat", "that the who"]
searchTerm = prompt("Testing?");
function count(sample, searchTerm)
{
for (i=0;i<sample.length;i++)
{
if (sample[i].indexOf(searchTerm) == -1)
{
return 0;
}
return count(sample.substring(sample.indexOf(searchTerm) + searchTerm.length), searchTerm) + 1;
}
}
alert(count(sample, searchTerm));
Rehashed code
search = ["cat fat hat mat", "that the who"];
var pattern = prompt('Search?');
function count(sample, searchTerm)
{
var count, i;
count = 0;
for (i=0; i < sample.length; i++)
{
if (sample[i].indexOf(searchTerm) !== -1)
{
count++;
}
}
return count;
}
count(search, pattern);
I've redone everything and it still gives no output.

There are a couple of problems with this code. The most immediate one is you are calling substring on an array and not a string.
return count(sample.substring ...
Likely you meant to say
return count(sample[i].substring ...
The second issue though is that you need to divide the logic up a bit. You need to divide it up into sections that count the occurrences in a word and that which iterates through the array. Today they are intertwined and results in odd behavior because you end up passing non-arrays to places expecting arrays
function count(sample, searchTerm) {
var num = 0;
for (i=0;i<sample.length;i++) {
var current = sample[i];
var index = current.indexOf(searchTerm);
while (index >= 0) {
num++;
index = current.indexOf(searchTerm, index + 1);
}
}
return num;
}
Working Fiddle: http://jsfiddle.net/wrNbL/

You don't need to use recursion here, just iterate through the array once counting if the search term matches.
function count(sample, searchTerm)
{
var count, i;
count = 0;
for (i=0; i < sample.length; i++)
{
if (sample[i].indexOf(searchTerm) !== -1)
{
count++;
}
}
return count;
}

Related

Function to check whether a combination of letters appears in a sequence of random words and determine where exactly are they

I created a function in javascript to generate a random string with a certain length in either uppercase/lowercase or both.
function randomString(max, option) {
var rNum = [];
if (option.toLowerCase() === "lowercase") {
for (let i = 0; i < max; i++) {
var randomNumber = Math.floor(Math.random() * (122 - 97) + 97);
rNum.push(randomNumber);
}
} else if (option.toLowerCase() === "uppercase") {
for (let i = 0; i < max; i++) {
var randomNumber = Math.floor(Math.random() * (90 - 65) + 65);
rNum.push(randomNumber);
}
} else if (option.toLowerCase() === "both") {
for (let i = 0; i < max; i++) {
var n = Math.floor(Math.random() * (122 - 65) + 65);
while ([91, 92, 93, 94, 95, 96].includes(n)) {
//If the random number is between 90 and 97 then we keep generating new numbers:
n = Math.floor(Math.random() * (122 - 65) + 65);
}
rNum.push(n);
}
} else {
return "Second parameter not valid, please type 'lowercase','uppercase' or 'both'";
}
var word = "";
for (let i = 0; i < rNum.length; i++) {
var letter = String.fromCharCode(rNum[i]);
word += letter;
}
return word;
}
Now I wanted to create a second function that given any string from the user, it checks whether that word appears in the randomly generated string.
I started it and honestly I simply have no idea how to do it. How do I check where in that long string there is indeed the word which I don't know how long it is. I guess it can see if it does exist or not, but how do i find its position? I tried using array.indexOf(userString), but it only returns the first time it appears.
function findWordsByChance(letters) {
var myString = randomString(999999, "both");
var splited = myString.split("");
if (splited.includes(letters)) {
console.log("this combination exists");
} else {
console.log("it doesnt");
}
for (let i = 1; i < splited.length - 1; i++) {
//check where it is (??)
}
}
findWordsByChance("Hi");
I'm still quite new to programming, so give me a break if I made any stupid mistakes :)
btw, if you guys got any tips on how to do something I already did but in a more efficient way, I'd appreciate.
indexOf accepts a second parameter which defines a start offset, so you can use this to loop through and find every occurrence. You just need to make the start point immediately past the last occurrence for each iteration. Here's how I'd write the function:
function indexOfAll(needle, haystack) {
var indices = [];
var index = 0;
while ((index = haystack.indexOf(needle, index)) > -1) {
indices.push(index);
index += needle.length;
}
return indices;
}
console.log(indexOfAll("oat", "goat in a boat"));
...but this may be easier for you to read:
function indexOfAll(needle, haystack) {
var indices = [];
var offset = 0;
while (haystack.indexOf(needle, offset) > -1) {
var indexOfThisOccurrence = haystack.indexOf(needle, offset);
indices.push(indexOfThisOccurrence);
offset = indexOfThisOccurrence + needle.length;
}
return indices;
}
console.log(indexOfAll("ug", "slug in a mug"));
You can use the simple .match() function in javascript to find a string in another string.
var myString = randomString(100, "both");
// myString = "fAuqxBfkXprhvRqOGLPmTiFbhrZtjXXMFwircAGBBtIkiDbGHPvYymMlabJyeAKUtIYNedUpNPlaeEcjIsSeEtOUriHTuCtbpNZX"
var result = myString.match('rZtjX');
// result[0] is your search string...the "letters" value
// result[1] is where the string was found
// If you want to get all occurrences where the search string was found you can use the function below.
findOccurrences = (needle, haystack) => {
const pieces = haystack.split(needle);
if (!pieces.length) {
return console.log('No Matches');
}
let index = 0;
pieces.forEach((piece) => {
index += piece.length;
console.log(needle, ' found at ', index);
index += needle.length;
});
}
findOccurrences('LPmT', myString);
LPmT found at 17
LPmT found at 47
LPmT found at 81
LPmT found at 99
LPmT found at 112
You could turn their input into a regex.
const inputRegex = new RegExp(input, 'g')
Then you could use string.matchAll() to get all instances of matches.
const matches = randomLetters.matchAll(inputRegex)
But that gives you an iterator. To have it as an array, you'd do this instead:
const matches = [...randomLetters.matchAll(inputRegex)]
Now, each item in matches is an object with a key index referring to its position on the string.
You can learn more at MDN.

How to do Nested For Loops in Functional Style

I'm in the process of learning functional programming, and completely getting rid of for loops has been a challenge sometimes, because they provide so much control and freedom. Below is an example of checking if a string is an isogram or not (no letters should be repeated). With nested for loops, it became an easy solution. Is there a way to do this the functional way with any high order functions or anything else? Any suggestion would be a huge help.
Code:
function isIsogram(string) {
let array = string.split('');
let condition = true;
for (let i = 0; i < string.length; i++) { //first loop picks character
for (j = i + 1; j < string.length; j++) { //second loop compares it rest
if (array[i].toLowerCase() == array[j].toLowerCase())
condition = false; //if repeat, the condition false
}
return condition;
}
}
You can use every or some together with a suitable string function:
function isIsogram(string) {
string = string.toLowerCase(); // case insensitive
return string.split('').every(function(character, index) {
return !string.includes(character, index+1);
});
}
Instead of includes you might also have utilised indexOf.
You can sort the String first and then apply every on it. It will stop the iteration as soon as two successive letters are the same:
Here is an improved implementation. Credit goes to #Xotic750:
function isIsogram(x) {
return Array.from(x.toLowerCase()).sort().every((y, i, xs) => i === 0
? true
: y !== xs[i - 1]);
}
console.log( isIsogram("consumptively") );
console.log( isIsogram("javascript") );
The implementation uses Array.prototype.every's second parameter, which represents the index of the current element (of the iteration). Please note that isIsogram solely depends on functions and their arguments.
Another example, like #Bergi but using some ES6 features for comparison.
function isIsogram(string) {
string = string.toLowerCase(); // case insensitive
for (let character of Array.from(string).entries()) {
if (string.includes(character[1], character[0] + 1)) {
return false;
}
}
return true;
}
console.log(isIsogram('abc'));
console.log(isIsogram('abca'));
How your ES3 style code could have looked (noting some of the issues pointed out in the comments)
function isIsogram(string) {
string = string.toLowerCase(); // case insensitive
var length = string.length;
for (var i = 0; i < length; i += 1) {
for (var j = i + 1; j < length; j += 1) {
if (string.charAt(i) === string.charAt(j)) {
return false;
}
}
}
return true;
}
console.log(isIsogram('abc'));
console.log(isIsogram('abca'));

String with the highest frequency of recurring letters in a word

This is a challenge for coderbyte I thought I'd try to do it using a different method for solving it than loops, objects. It passed but it isn't perfect. The directions for the challenge are:
Have the function LetterCountI(str) take the str parameter being passed and return the first word with the greatest number of repeated letters. For example: "Today, is the greatest day ever!" should return greatest because it has 2 e's (and 2 t's) and it comes before ever which also has 2 e's. If there are no words with repeating letters return -1. Words will be separated by spaces.
function LetterCountI(str){
var wordsAndLetters = {};
var count = 0;
var finalword;
str = str.split(" ");
for(var i = 0; i < str.length; i++){
wordsAndLetters[str[i]] = wordsAndLetters[str[i]] || 0;
}
function countWordLetters(strs){
strs = strs.split("");
var lettercount = {};
for(var i = 0; i <strs.length; i++){
lettercount[strs[i]] = lettercount[strs[i]] || 0;
lettercount[strs[i]]++;
}
return lettercount;
}
for(var words in wordsAndLetters){
wordsAndLetters[words] = countWordLetters(words);
var highestLetterFrequency = wordsAndLetters[words];
for(var values in highestLetterFrequency){
if(highestLetterFrequency[values] > count){
count = highestLetterFrequency[values];
finalword = words;
}
if(count !== 1){
return finalword;
}
}
}
return -1;
}
LetterCountI("today is the greatest day ever!");
Sorry if some of the variable names are confusing I've been up for far too long trying to figure out what I did wrong. If you use the parameters at the bottom of the code it returns 'greatest' like it should however change the parameters to
LetterCountI("toddday is the greatttttest day ever!");
and it logs 'toddday' when it should log 'greatttttest'. Is my code completely wrong? I realize if the parameters were ("caatt dooog") it should log 'caatt' since there are 4 recurring letters but I'm not worried about that I just am concerned about it finding the most recurrence of one letter(but by all means if you have a solution I would like to hear it!). Any changes to the variables if needed to make this code more readable would be appreciated!
The problem with your code is the positioning of the following section of code:
if(count !== 1){
return finalword;
}
Move it from where it currently is to just before the return -1, like so:
for(var words in wordsAndLetters){
wordsAndLetters[words] = countWordLetters(words);
var highestLetterFrequency = wordsAndLetters[words];
for(var values in highestLetterFrequency){
if(highestLetterFrequency[values] > count){
count = highestLetterFrequency[values];
finalword = words;
}
}
}
if(count !== 1){
return finalword;
}
return -1;
The problem with your original code is that your were returning the first word that had repeating characters, which meant your code didn't get far enough to check if any subsequent words had more repeating characters.
Also, just for fun, here is my alternative solution.
Here you go
Array.prototype.getUnique = function(){
var u = {}, a = [];
for(var i = 0, l = this.length; i < l; ++i){
if(u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
function LetterCountI(str){
var temp = str.split(" ");
var final = '', weight = 0;
for(var i = 0; i < temp.length; ++i) {
var word = temp[i].split("");
if(word.getUnique().length < word.length) {
var diff = word.length - word.getUnique().length;
if(diff > weight){
weight = diff;
final = temp[i];
}
}
}
return final;
}
console.log(LetterCountI("Catt dooog"));
console.log(LetterCountI("toddday is the greatttttest day ever!"));
Viva LinQ !!!!!
var resultPerWord = new Dictionary<string, int>();
var S = "toddday is the greatttttest day ever!";
foreach(var s in S.Split(' '))
{
var theArray =
from w in s
group w by w into g
orderby g.Count() descending
select new { Letter = g.Key, Occurrence = g.Count() };
resultPerWord.Add(s, theArray.First().Occurrence);
}
var r = "-1";
if (resultPerWord.Any(x => x.Value >1))
{
r = resultPerWord.OrderByDescending(x => x.Value).First().Key;
}

Showing unique characters in a string only once

I have a string with repeated letters. I want letters that are repeated more than once to show only once.
Example input: aaabbbccc
Expected output: abc
I've tried to create the code myself, but so far my function has the following problems:
if the letter doesn't repeat, it's not shown (it should be)
if it's repeated once, it's show only once (i.e. aa shows a - correct)
if it's repeated twice, shows all (i.e. aaa shows aaa - should be a)
if it's repeated 3 times, it shows 6 (if aaaa it shows aaaaaa - should be a)
function unique_char(string) {
var unique = '';
var count = 0;
for (var i = 0; i < string.length; i++) {
for (var j = i+1; j < string.length; j++) {
if (string[i] == string[j]) {
count++;
unique += string[i];
}
}
}
return unique;
}
document.write(unique_char('aaabbbccc'));
The function must be with loop inside a loop; that's why the second for is inside the first.
Fill a Set with the characters and concatenate its unique entries:
function unique(str) {
return String.prototype.concat.call(...new Set(str));
}
console.log(unique('abc')); // "abc"
console.log(unique('abcabc')); // "abc"
Convert it to an array first, then use Josh Mc’s answer at How to get unique values in an array, and rejoin, like so:
var nonUnique = "ababdefegg";
var unique = Array.from(nonUnique).filter(function(item, i, ar){ return ar.indexOf(item) === i; }).join('');
All in one line. :-)
Too late may be but still my version of answer to this post:
function extractUniqCharacters(str){
var temp = {};
for(var oindex=0;oindex<str.length;oindex++){
temp[str.charAt(oindex)] = 0; //Assign any value
}
return Object.keys(temp).join("");
}
You can use a regular expression with a custom replacement function:
function unique_char(string) {
return string.replace(/(.)\1*/g, function(sequence, char) {
if (sequence.length == 1) // if the letter doesn't repeat
return ""; // its not shown
if (sequence.length == 2) // if its repeated once
return char; // its show only once (if aa shows a)
if (sequence.length == 3) // if its repeated twice
return sequence; // shows all(if aaa shows aaa)
if (sequence.length == 4) // if its repeated 3 times
return Array(7).join(char); // it shows 6( if aaaa shows aaaaaa)
// else ???
return sequence;
});
}
Using lodash:
_.uniq('aaabbbccc').join(''); // gives 'abc'
Per the actual question: "if the letter doesn't repeat its not shown"
function unique_char(str)
{
var obj = new Object();
for (var i = 0; i < str.length; i++)
{
var chr = str[i];
if (chr in obj)
{
obj[chr] += 1;
}
else
{
obj[chr] = 1;
}
}
var multiples = [];
for (key in obj)
{
// Remove this test if you just want unique chars
// But still keep the multiples.push(key)
if (obj[key] > 1)
{
multiples.push(key);
}
}
return multiples.join("");
}
var str = "aaabbbccc";
document.write(unique_char(str));
Your problem is that you are adding to unique every time you find the character in string. Really you should probably do something like this (since you specified the answer must be a nested for loop):
function unique_char(string){
var str_length=string.length;
var unique='';
for(var i=0; i<str_length; i++){
var foundIt = false;
for(var j=0; j<unique.length; j++){
if(string[i]==unique[j]){
foundIt = true;
break;
}
}
if(!foundIt){
unique+=string[i];
}
}
return unique;
}
document.write( unique_char('aaabbbccc'))
In this we only add the character found in string to unique if it isn't already there. This is really not an efficient way to do this at all ... but based on your requirements it should work.
I can't run this since I don't have anything handy to run JavaScript in ... but the theory in this method should work.
Try this if duplicate characters have to be displayed once, i.e.,
for i/p: aaabbbccc o/p: abc
var str="aaabbbccc";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 ){
return obj;
}
}
).join("");
//output: "abc"
And try this if only unique characters(String Bombarding Algo) have to be displayed, add another "and" condition to remove the characters which came more than once and display only unique characters, i.e.,
for i/p: aabbbkaha o/p: kh
var str="aabbbkaha";
Array.prototype.map.call(str,
(obj,i)=>{
if(str.indexOf(obj,i+1)==-1 && str.lastIndexOf(obj,i-1)==-1){ // another and condition
return obj;
}
}
).join("");
//output: "kh"
<script>
uniqueString = "";
alert("Displays the number of a specific character in user entered string and then finds the number of unique characters:");
function countChar(testString, lookFor) {
var charCounter = 0;
document.write("Looking at this string:<br>");
for (pos = 0; pos < testString.length; pos++) {
if (testString.charAt(pos) == lookFor) {
charCounter += 1;
document.write("<B>" + lookFor + "</B>");
} else
document.write(testString.charAt(pos));
}
document.write("<br><br>");
return charCounter;
}
function findNumberOfUniqueChar(testString) {
var numChar = 0,
uniqueChar = 0;
for (pos = 0; pos < testString.length; pos++) {
var newLookFor = "";
for (pos2 = 0; pos2 <= pos; pos2++) {
if (testString.charAt(pos) == testString.charAt(pos2)) {
numChar += 1;
}
}
if (numChar == 1) {
uniqueChar += 1;
uniqueString = uniqueString + " " + testString.charAt(pos)
}
numChar = 0;
}
return uniqueChar;
}
var testString = prompt("Give me a string of characters to check", "");
var lookFor = "startvalue";
while (lookFor.length > 1) {
if (lookFor != "startvalue")
alert("Please select only one character");
lookFor = prompt(testString + "\n\nWhat should character should I look for?", "");
}
document.write("I found " + countChar(testString, lookFor) + " of the<b> " + lookFor + "</B> character");
document.write("<br><br>I counted the following " + findNumberOfUniqueChar(testString) + " unique character(s):");
document.write("<br>" + uniqueString)
</script>
Here is the simplest function to do that
function remove(text)
{
var unique= "";
for(var i = 0; i < text.length; i++)
{
if(unique.indexOf(text.charAt(i)) < 0)
{
unique += text.charAt(i);
}
}
return unique;
}
The one line solution will be to use Set. const chars = [...new Set(s.split(''))];
If you want to return values in an array, you can use this function below.
const getUniqueChar = (str) => Array.from(str)
.filter((item, index, arr) => arr.slice(index + 1).indexOf(item) === -1);
console.log(getUniqueChar("aaabbbccc"));
Alternatively, you can use the Set constructor.
const getUniqueChar = (str) => new Set(str);
console.log(getUniqueChar("aaabbbccc"));
Here is the simplest function to do that pt. 2
const showUniqChars = (text) => {
let uniqChars = "";
for (const char of text) {
if (!uniqChars.includes(char))
uniqChars += char;
}
return uniqChars;
};
const countUnique = (s1, s2) => new Set(s1 + s2).size
a shorter way based on #le_m answer
let unique=myArray.filter((item,index,array)=>array.indexOf(item)===index)

Checking and deleting multiple occurrences of the same value in an array using javascript

This is what I've been trying, but something is wrong with the last part, can sy please tell me whats wrong, or show me an other method of doing this. Thanks in advance.
function removeSpaces(string) {
var str = string.replace(/^\s*|\s*$/g,'')
str = str.replace(/[^a-z|A-z|\r\n]/g,'');
while (str.indexOf("\r\n\r\n") >= 0) {
str = str.replace(/\r\n\r\n/g, "\r\n");
}
words = str.split("\r\n");
var i = 0;
var j = 0;
for (i = 0; i < words.length; i++) {
for (j = i; j < words.length; j++) {
if ((i != j) && (words[i] == words[j])) {
words.splice(j,1);
j--;
}
}
}
str = words.join("\r\n");
return str;
}
You could use the filter function. The filter function of an array is returning an array containing elements which pass to a certain filter.
var isLastElement = function(element, index, array){
return (index == array.lastIndexOf(element));
};
words = words.filter(isLastElement);
In this example, the filter function goes through the elements of the initial array ad add this element to the new array only if isLastElement(element, elementIndex, initArray) return true.
The isLastElement function returns true only if the element is not present a second time in the end of the array.

Categories