Here is the prompt: Write a function that will return the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string. The input string can be assumed to contain only alphabets (both uppercase and lowercase) and numeric digits.
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
Get all unique values in a JavaScript array (remove duplicates)
I used variances of the above questions/answers and tried to amend it for what I am looking for- the count of how many elements are found more than once
var arr = 'Indivisibilities';
var sorted_arr = arr.toLowerCase().split('').sort();
let count = 0;
let duplicateCount = (parm1) => {
for (var i = 0; i < sorted_arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
count ++;
}
} return count;
}
duplicateCount(arr);
Count returns 7, what is expected is 2. Also, I would really like to avoid using a for loop. I'm hoping this can be done with .forEach or something method. ** I'm still pretty knew to code so please try not to do any one liners :) I appreciate the efficiency, but I'm still trying to understand the logic
You can use reduce and filter
Change string to lowercase
Split string by ''
Use each element as key, if it is already present increase it's count by 1 else set it to 1
Filter values which are greater than 1 to see duplicates
Get length of filtered array
var str = 'Indivisibilities';
let duplicateCount = (str) => {
let dups = str.toLowerCase().split('').reduce((op,inp)=>{
op[inp] = op[inp] || 0
op[inp]++
return op
},{})
return Object.values(dups).filter(v=>v>1).length
}
console.log(duplicateCount(str));
Related
I've done something similar in the past with a nested loop, but for some reason I can't get my mind around this to get it to work. I keep running into problems that involve indexing of two separate arrays and it's been a continual stumbling block
In this case, I'm trying to sort a string. The string includes letters and numbers, the task is to sort the letters in reverse alphabetical order while keeping the numbers at their same index.
I've come up with this solution (probably not the most efficient), but can't get the sortString array to come together so that I can join the letters and numbers back into a string.
function reverse(str) {
// split the str into an array
const arr = [...str]
// converts each element in arr to a number, letters are string 'NaN'
const numArray = arr.map(x=> Number(x)).map(x=> x >= 0 ? x : String(x))
// array of the sorted letters
const letters = arr.filter(x=> !/[0-9]/g.test(x)).reverse()
// initiate empty array to hold the combined numbers and letters
let sortString = []
// Use for loop to cycle through and replace elements that are 'NaN' with letters from the letter array. All pushed to sortString.
for (let i=0; i<arr.length; i++) {
sortString.push(numArray[i] === 'NaN' ? letters[0] : numArray[i])
}
return sortString
}
reverse("ab89c") // output should be "cb89a"
You could get an array of non digits, sort it and map the splitted string with the sorted letters in places if not a digit.
const
reverse = string => {
const
array = Array.from(string),
letters = array
.filter(v => /\D/.test(v))
.sort();
return array
.map(v => /\D/.test(v) ? letters.pop() : v)
.join('');
};
console.log(reverse("ab89c"));
A slightly different approach takes a Proxy for the wanted items of sorting:
How to sort only part of array? between given indexes
Here's code that works:
Explanation of how the code works is in-line as comments.
Basically it takes the numbers out, sorts the letters in reverse, and puts the sorted letters back in the right place.
Because it's step-by-step, you could add console log on each variable after it's assigned to see how it works step by step.
function reverse(input) {
// This function from: https://stackoverflow.com/a/32567789/569302
function testIsLetter(c) {
return c.toLowerCase() != c.toUpperCase();
}
// Convert from array to string to process character by character
let inputAsArray = input.split('');
// This is where we'll lookup where to put the letters when we're done
let mapped = inputAsArray.map((s) => {
return {
s,
isLetter: testIsLetter(s)
}
})
// Now that we've captured where the letters are, take the numbers (non-letters) out
let filtered = mapped.filter(m => m.isLetter)
// Convert the object into just letters so they're easily compared when we sort
let filteredAsLettersArray = filtered.map(f => f.s)
// Sort ascending
filteredAsLettersArray.sort()
// Reverse to sort descending
filteredAsLettersArray.reverse()
// Now we need to put the letters back.
let resultAsArray = [];
let letterIndex = 0;
mapped.forEach(m => {
// If it's a letter, we use the sorted result (incrementing letterIndex each time)
if (m.isLetter) {
resultAsArray.push(filteredAsLettersArray[letterIndex]);
letterIndex++;
} else {
// Otherwise we use the number
resultAsArray.push(m.s);
}
});
let result = resultAsArray.join('');
return result;
}
console.log(reverse("ab89c"));
console.log(reverse("1a2eb8f9c"));
I am currently on the codewars site trying to improve my JavaScript along with other things. This question will give an input like this
'is2 Thi1s T4est 3a' and expect an output like this 'Thi1s is2 3a T4est'
I am having trouble indexing the string. It seems odd as I've done it before in Python but even trying this in Python I don't get the proper output.
Here is my code, before it was giving me at least an array of the numbers but now I just get [ Array(4) ].
I know that the proper output should be a string but once I get it all in an array I plan to just tempSentence.join(" ") the array and return it. Sorry that is kind of messy but I kept trying different things:
function order(words){
let hasNumber = /\d/;
let newSentence = words.split(" ")
let tempSentence = words.split(" ")
for (let i = 0; i < newSentence.length; i++){
for (let j = 0; j < newSentence[i].length; j++){
if (hasNumber.test(newSentence[i][j])){
tempSentence[words[i][j]-1] = newSentence[i]
}
}
}
return tempSentence
}
Creating two separate arrays and trying to rearrange indicies in a nested loop seems quite convoluted for what you're trying to accomplish. An easier approach would be to take just one array of words, and .sort it by having a helper function that extracts the digit from it, and comparing the extracted number of the two elements being compared inside the callback.
const getNum = word => word.match(/\d+/)[0];
const order = (words) => words
.split(' ')
.sort((a, b) => getNum(a) - getNum(b))
.join(' ');
console.log(order('is2 Thi1s T4est 3a'));
I am pretty new to programming and I was solving a problem on code wars which is as follows:
Question:
Write a function that will find all the anagrams of a word from a list. You will be given two inputs a word and an array with words. You should return an array of all the anagrams or an empty array if there are none.
This is my code
function anagrams(word, words) {
let word_Array = word.split('').sort()
let total = []
for (x = 0; x<words.length; x++) {
if(words[x].split('').sort() === word_Array) {
total.push(words[x])
} return total
}
}
The result should look something like this
anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']) => ['aabb', 'bbaa']
I keep getting an empty array when I run my code. Please can someone tell me the error in my code. Thank you
Please take a look at the following snippet.
const sort = (word) => word.split('').sort().join('');
function anagrams(word, words) {
let token = sort(word);
let total = []
for (let x = 0; x < words.length; x++) {
if (sort(words[x]) === token) {
total.push(words[x])
}
}
return total
}
console.log(anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']));
You are on the right track but missed a few details.
As others have mentioned you cant just compare discrete arrays with ===. The best you can do is an element wise compare. You dont really need to this if you compare normal value types such as numbers, strings, bools, ect. If you join the sorted string back its much easier to compare using built in operators such as ===.
Your control logic is wrong. Notice how you are returning straight from the loop? It means that at most you would ever get one results since the loop cant iterative over the full loop condition.
You should always qualify your variable declarations with let/const. This was missing in the for loop and would declare x as a global.
Improvements
You could replace the for loop with a for of and not have to worry about indexing.
for (let w of words) {
console.log(w); // we no longer have to worry about words[i].
}
Even better you could replace the entire for and array.push logic with a simple array.filter
const sort = (word) => word.split('').sort().join('');
function anagrams(word, words) {
let token = sort(word);
return words.filter((w) => sort(w) === token);
}
console.log(anagrams('abba', ['aabb', 'abcd', 'bbaa', 'dada']));
Array is Object in JavaScript, which is reference type.
So you can not use "===" to check whether two arrays are equals.
For example:
var array1=[1,2];
var array2=[1,2];
var result = array1 === array2;
the result will be false.
My suggestion is writing a new function to check whether two arrays are equals by comparing the items.
function areEquals(array1, array2){
if(array1.length!==array2.length){
return false;
}
for(var i in array1){
if(array1[i]!==array2[i]){
return false;
}
}
return true;
}
I'm working on an assignment where I have to find the smallest positive integer greater than 0 that is NOT within a huge array including 100,000 elements. I'm able to do it so it's correct but apparently my solution takes way too long and returns a timeout error.
this is my current solution:
function solution(A) {
let min=1
while(A.includes(min) === true){
min++
}
return min
}
Is there a faster way of doing this that doesn't involve looping through every single element?
edit: whoops guys I forgot a key element to this question!
edit 2: the minimum value would be -2 and the maximum value would be 100,000 and they are not in order
You could take an object and add each wanted value to the object.
Then take the smallest key and check if is is equal to one and increment until no key is found. Otherwise return one.
function getSmallest(array) {
let temp = Object.create(null),
smallest;
for (const v of array) if (v > 0) temp[v] = true;
smallest = +Object.keys(temp)[0];
if (smallest !== 1) return 1;
while (temp[++smallest]);
return smallest;
}
console.log(getSmallest([2, 1, 0])); // 3
console.log(getSmallest([2, 3, 0])); // 1
I do believe this is a test to see if you know search algorithms for an unsorted array. Have you been taught about binary search?
I wrote code for following statement: "Find minimal positive integer NOT in array of numbers that could be any from -2 to 10000".
const arr = [5,4,6,7,5,6,4,5];
const p = new Array(10004);
arr.forEach(el => p[el + 2] = 1);
let answer = 10004;
for (let i = 3; i < 10004; ++i) {
if (!p[i]) {
answer = i - 2;
console.log(answer);
break;
} else if (i == 10003) {
console.log('no solution');
}
}
Sorting the array seems like a good place to start. Then you can loop or binary search from there to find your smallest positive integer.
How can I make a search function using regEx?
I have some code but can't post it at the moment due to my computer being very broken and annoying, I will try again tomorrow!
This is not really what would be called combinations, but permutations.
The idea is to use recursion for getting the result for a shorter array, i.e. the one that lacks the first element.
Then take all permutations you get back from the recursive call, and insert the left-out value in each possible index.
When input has duplicates, then you need to stop inserting the left-out value as soon as you find that same value preceding the insertion spot.
Here is how that looks:
function scramble(array) {
if (array.length == 0) {
return [[]];
}
let results = [];
// solve the problem for a shorter array (first value excluded), and iterate:
for (let perm of scramble(array.slice(1))) {
// add the missing element in each possible position:
for (let i = 0; i < array.length; i++) {
// next IF is only needed when input has duplicates, and
// output should not repeat same array:
if (i && array[0] === perm[i-1]) break;
results.push(perm.slice(0, i).concat(array[0], perm.slice(i)));
}
}
return results;
}
let array = ["I", "am", "coding", "am"];
console.log(scramble(array));
Without the inner if, an input with duplicate values will produce duplicate arrays. If this is not desired, then the if is needed.
You could iterate and get a flat array of the mapping of the value with the result of the nested calls.
function permutation(array) {
return array.length === 1
? [array]
: array.flatMap((v, i) => permutation([
...array.slice(0, i),
...array.slice(i + 1)
]).map(a => [v, ...a]));
}
permutation(["I", "am", "coding"]).map(a => console.log(...a));