I'm working through some "Kata's" on CodeWars.com, and am stuck on the Permutations problem.
Here is the problem: n this kata you have to create all permutations
of an input string and remove duplicates, if present. This means, you
have to shuffle all letters from the input in all possible orders.
Examples:
permutations('a'); // ['a']
permutations('ab'); // ['ab', 'ba']
permutations('aabb'); // ['aabb', 'abab', 'abba', 'baab', 'baba', 'bbaa']
The order of the permutations doesn't matter.
Here is my solution:
function permutations(string) {
const swap = (string, x, y) => {
const stringArray = string.split('')
const swapVar = stringArray[x]
stringArray[x] = stringArray[y]
stringArray[y] = swapVar
return stringArray.join('')
}
const permutate = (k, arr) => {
if (k === 1) {
return arr
} else {
for (let i = 0; i < k - 1; i++) {
if (k % 2 === 0) {
arr.push(swap(string, i, k-1))
} else {
arr.push(swap(string, 0, k-1))
}
}
permutate(k - 1, arr)
}
}
return permutate(string.length, [string])
}
When you pass in a single letter, it works fine. Two letters and it returns undefined. I've console logged the if statement block with the return and it should be returning the correct answer, but the result is still undefined. Considering it's getting the correct answer in the if statement and isn't progressing into the else block, I'm at a loss for why this isn't working.
Thank you in advance!
I figured it out - I was missing the return statement before the recursive function call.
Here is a basic solution
String.prototype.replaceAt = function(index, replacement) {
return this.substr(0, index) + replacement + this.substr(index +
replacement.length);}
var words = [];
var string = "lyes";
for(var i = 0;i< string.length;i++){
for(var j = 0;j<string.length;j++){
var tempChar;
if(i!==j){
tempChar = string[j]
var str = string.replaceAt(j,string[i])
str = str.replaceAt(i,tempChar)
if(!words.includes(str)){
words.push(str)
console.log(str)
}
}
}
}
console.log(words.length +" words found")
Related
This code is supposed to take in a string and return and return the string without vowels.
As you can see from the ouput below, it is working because it returns the first Coding is driving me crzy without a in crazy, and the 2nd without e and so on...
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
let vowels = ['a','e','i','o','u'];
for (const vowel of vowels) {
for (let i = 0; i < charactersArray.length; i++) {
if (vowel === charactersArray[i]) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
//OUTPUT ON ONE LINE
//Coding is driving me crzy Coding is driving m crazy Codng s drvng me crazy Cding is driving me crazy Coding is driving me crazy
As suggested in one of the comments. Break down the problem by creating an isVowel() function and iterate over all chars in the string only once to check if a given character is a vowel:
function isVowel(c) {
return ['a','e','i','o','u'].includes(c);
};
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
for (let i = 0; i < charactersArray.length; i++) {
if (isVowel(charactersArray[i])) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
This code runs in O(n * k) time complexity, where n is the length of the string and k is the number of vowels in English language (which is 5. So overall complexity is O(5n) = O(5).
You can use the includes method to check if the word of charactersArray[i] is a vowel, with a single loop is enought
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
let vowels = ['a','e','i','o','u'];
for (let i = 0; i < charactersArray.length; i++) {
if (vowels.includes(charactersArray[i])) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
If you want to match only the vowels you can make this:
function removeVowelFromString(string) {
let newCharactersArray = [];
charactersArray = string.split('');
let vowels = ['a','e','i','o','u'];
for (let i = 0; i < charactersArray.length; i++) {
if (!vowels.includes(charactersArray[i])) {
continue;
}
else {
newCharactersArray.push(charactersArray[i]);
}
}
return newCharactersArray.join('');
}
console.log(removeVowelFromString('Coding is driving me crazy '));
Here are some docs you could refer to :
string.includes
Spread Syntax
Filter
LowerCase
//you could do it like
function removeVowelFromString(string) {
let vowels = "aeiou";
return [...string].filter(x => !vowels.includes(x.toLowerCase())).join("");
}
console.log(removeVowelFromString("Will remove vowels from this string"))
I hope i was able to help.
// Create a function that takes a string and turns it into a Mexican Wave.
var smallarr=[]
var bigarr=[]
var another=""
function wave(str){
for (var i=0;i<str.length;i++){
smallarr.push(str)
}
for (var j=0;j<smallarr.length;j++)
{
if(smallarr[j][j].toUpperCase()==smallarr[j][j])
{
var c=smallarr[j][j].toLowerCase()
smallarr[j][j]=c
}
else {
var c=smallarr[j][j].toUpperCase()
smallarr[j][j]=c}
}
}
return smallarr
}
document.write(wave("edabit"))
//console.log(smallarr)
The output I expect is wave("edabit") ➞ ["Edabit", "eDabit", "edAbit", "edaBit", "edabIt", "edabiT"] but now the output is the same as the input.
Any advice is appreciated.
You can split the input string into an array of characters and then map over it replacing the current character with it's uppercase version:
const wave = (str) => {
return str
.split('')
.map((char, index) =>
str.substr(0, index) + char.toUpperCase() + str.substr(index + 1))
}
console.log(wave('edabit'));
You can use Array.from() to create an array from the string. In the callback (mapFn) get the current letter, and the current index, use them with String.substring() to build a new string with the uppercased letter.
const fn = str => Array.from(str, (c, i) =>
str.substring(0, i) + c.toUpperCase() + str.substring(i + 1)
);
const result = fn('edabit');
console.log(result);
You can try double Array.map() where second callback argument represents an index:
let input = "edabit";
let result = input.split('').map(
(_, i) => input.split('').map(
(char, j) => i === j ? char.toUpperCase() : char).join()
);
console.log(result);
EDIT:
The problem with your approach is that strings are immutable so you need to build a new string using slice like below:
var smallarr=[]
var bigarr=[]
var another=""
function wave(str){
for (var i=0;i<str.length;i++){
smallarr.push(str)
}
for (var j=0;j<smallarr.length;j++){
smallarr[j] = smallarr[j].slice(0,j) + smallarr[j][j].toUpperCase() + smallarr[j].slice(j+1);
}
return smallarr
}
document.write(wave("edabit"))
console.log(smallarr)
or just using one loop:
function wave(str){
var smallarr=[]
for (var i=0;i<str.length;i++){
smallarr.push(str.slice(0,i) + str[i].toUpperCase() + str.slice(i+1))
}
return smallarr
}
console.log(wave("edabit"))
The main issue with your code is that you try to update a character in a string, but that is not possible. In JavaScript strings are immutable. Trying to assign to a certain index will have no effect to the string.
Instead you must rebuild a string where that one character is different. You can use slice to take parts of the string to help you build it.
Here is your code adapted to that effect:
function wave(str) {
var smallarr = []; // define as local
for (var j = 0; j < str.length; j++) {
let c = str[j]; // Use a variable to avoid duplicate code
if (c.toUpperCase() === c) {
c = c.toLowerCase();
} else {
c = c.toUpperCase();
}
// You cannot modify a string; you need to regenerate one
smallarr.push(str.slice(0, j) + c + str.slice(j+1));
}
return smallarr
}
console.log(wave("edabit"))
String.prototype.replaceAt=function(index, char) {
var a = this.split("");
a[index] = char;
return a.join("");
}
const createEdibet = ( word ) => {
console.log('word ' + word.split(''));
let array = word.split('')
array.map((letter, i) => {
let a = word.replaceAt(i, letter.toUpperCase());
console.log(a);
return a;
});
console.log(array)
// console.log(words)
}
createEdibet('edabit');
You could split the string, map the array and take the splittes string for another mapping by checking the index and use an upper case letter for matching indices.
const
wave = (string) => string
.split('')
.map((_, i, splitted) => splitted.map((c, j) => i === j ? c.toUpperCase() : c).join(''));
};
console.log(wave('edabit'));
A classic approach
function wave(string) {
var result = [],
i, j, temp;
for (i = 0; i < string.length; i++) {
temp = '';
for (j = 0; j < string.length; j++) {
temp += i === j ? string[j].toUpperCase() : string[j];
}
result.push(temp);
}
return result;
}
console.log(wave('edabit'));
If the array length is small you can use split, map, join like this:
let text = `edabit`;
let results = text.split('').map((char,index,original)=>{
let temp = [...original];
temp[index]=temp[index].toUpperCase();
return temp.join('');
});
console.log(results);
But in big array it's not optimized.
Hey I have a small problem. So basically I'm passing string to function as an argument, then converting it to array and I'm trying to compare generated array elements with one another and if they are equal it should return ")" else "(", but there is problem when comparing elements and the values are wrong. Maybe someone could help me.
function duplicateEncode(word) {
let splitString = word.split("");
let newArr = splitString.map((val, index, arr) => {
for (let i = 0; i < splitString.length; i++) {
if (val === arr[i]) {
return ')';
} else {
return '(';
}
}
});
return newArr.join('');
}
Use Javascript's Map object to store if current letter exists or not.
function duplicateEncode(word){
let m = new Map();
let splitString= word.split("");
let coded = "";
splitString.map( s => {
if(!m[s]){
m[s] = true
coded += "("
} else {
coded += ")"
}
})
return coded
}
console.log(duplicateEncode("stack"))
I saw this interview question and gave a go. I got stuck. The interview question is:
Given a string
var s = "ilikealibaba";
and a dictionary
var d = ["i", "like", "ali", "liba", "baba", "alibaba"];
try to give the s with min space
The output may be
i like alibaba (2 spaces)
i like ali baba (3 spaces)
but pick no.1
I have some code, but got stuck in the printing.
If you have better way to do this question, let me know.
function isStartSub(part, s) {
var condi = s.startsWith(part);
return condi;
}
function getRestStr(part, s) {
var len = part.length;
var len1 = s.length;
var out = s.substring(len, len1);
return out;
}
function recPrint(arr) {
if(arr.length == 0) {
return '';
} else {
var str = arr.pop();
return str + recPrint(arr);
}
}
// NOTE: have trouble to print
// Or if you have better ways to do this interview question, please let me know
function myPrint(arr) {
return recPrint(arr);
}
function getMinArr(arr) {
var min = Number.MAX_SAFE_INTEGER;
var index = 0;
for(var i=0; i<arr.length; i++) {
var sub = arr[i];
if(sub.length < min) {
min = sub.length;
index = i;
} else {
}
}
return arr[index];
}
function rec(s, d, buf) {
// Base
if(s.length == 0) {
return;
} else {
}
for(var i=0; i<d.length; i++) {
var subBuf = [];
// baba
var part = d[i];
var condi = isStartSub(part, s);
if(condi) {
// rest string
var restStr = getRestStr(part, s);
rec(restStr, d, subBuf);
subBuf.unshift(part);
buf.unshift(subBuf);
} else {
}
} // end loop
}
function myfunc(s, d) {
var buf = [];
rec(s, d, buf);
console.log('-- test --');
console.dir(buf, {depth:null});
return myPrint(buf);
}
// Output will be
// 1. i like alibaba (with 2 spaces)
// 2. i like ali baba (with 3 spaces)
// we pick no.1, as it needs less spaces
var s = "ilikealibaba";
var d = ["i", "like", "ali", "liba", "baba", "alibaba"];
var out = myfunc(s, d);
console.log(out);
Basically, my output is, not sure how to print it....
[ [ 'i', [ 'like', [ 'alibaba' ], [ 'ali', [ 'baba' ] ] ] ] ]
This problem is best suited for a dynamic programming approach. The subproblem is, "what is the best way to create a prefix of s". Then, for a given prefix of s, we consider all words that match the end of the prefix, and choose the best one using the results from the earlier prefixes.
Here is an implementation:
var s = "ilikealibaba";
var arr = ["i", "like", "ali", "liba", "baba", "alibaba"];
var dp = []; // dp[i] is the optimal solution for s.substring(0, i)
dp.push("");
for (var i = 1; i <= s.length; i++) {
var best = null; // the best way so far for s.substring(0, i)
for (var j = 0; j < arr.length; j++) {
var word = arr[j];
// consider all words that appear at the end of the prefix
if (!s.substring(0, i).endsWith(word))
continue;
if (word.length == i) {
best = word; // using single word is optimal
break;
}
var prev = dp[i - word.length];
if (prev === null)
continue; // s.substring(i - word.length) can't be made at all
if (best === null || prev.length + word.length + 1 < best.length)
best = prev + " " + word;
}
dp.push(best);
}
console.log(dp[s.length]);
pkpnd's answer is along the right track. But word dictionaries tend to be quite large sets, and iterating over the entire dictionary at every character of the string is going to be inefficient. (Also, saving the entire sequence for each dp cell may consume a large amount of space.) Rather, we can frame the question, as we iterate over the string, as: given all the previous indexes of the string that had dictionary matches extending back (either to the start or to another match), which one is both a dictionary match when we include the current character, and has a smaller length in total. Generally:
f(i) = min(
f(j) + length(i - j) + (1 if j is after the start of the string)
)
for all j < i, where string[j] ended a dictionary match
and string[j+1..i] is in the dictionary
Since we only add another j when there is a match and a new match can only extend back to a previous match or to the start of the string, our data structure could be an array of tuples, (best index this match extends back to, total length up to here). We add another tuple if the current character can extend a dictionary match back to another record we already have. We can also optimize by exiting early from the backwards search once the matched substring would be greater than the longest word in the dictionary, and building the substring to compare against the dictionary as we iterate backwards.
JavaScript code:
function f(str, dict){
let m = [[-1, -1, -1]];
for (let i=0; i<str.length; i++){
let best = [null, null, Infinity];
let substr = '';
let _i = i;
for (let j=m.length-1; j>=0; j--){
let [idx, _j, _total] = m[j];
substr = str.substr(idx + 1, _i - idx) + substr;
_i = idx;
if (dict.has(substr)){
let total = _total + 1 + i - idx;
if (total < best[2])
best = [i, j, total];
}
}
if (best[0] !== null)
m.push(best);
}
return m;
}
var s = "ilikealibaba";
var d = new Set(["i", "like", "ali", "liba", "baba", "alibaba"]);
console.log(JSON.stringify(f(s,d)));
We can track back our result:
[[-1,-1,-1],[0,0,1],[4,1,6],[7,2,10],[11,2,14]]
[11, 2, 14] means a total length of 14,
where the previous index in m is 2 and the right index
of the substr is 11
=> follow it back to m[2] = [4, 1, 6]
this substr ended at index 4 (which means the
first was "alibaba"), and followed m[1]
=> [0, 0, 1], means this substr ended at index 1
so the previous one was "like"
And there you have it: "i like alibaba"
As you're asked to find a shortest answer probably Breadth-First Search would be a possible solution. Or you could look into A* Search.
Here is working example with A* (cause it's less bring to do than BFS :)), basically just copied from Wikipedia article. All the "turning string into a graph" magick happens in the getNeighbors function
https://jsfiddle.net/yLeps4v5/4/
var str = 'ilikealibaba'
var dictionary = ['i', 'like', 'ali', 'baba', 'alibaba']
var START = -1
var FINISH = str.length - 1
// Returns all the positions in the string that we can "jump" to from position i
function getNeighbors(i) {
const matchingWords = dictionary.filter(word => str.slice(i + 1, i + 1 + word.length) == word)
return matchingWords.map(word => i + word.length)
}
function aStar(start, goal) {
// The set of nodes already evaluated
const closedSet = {};
// The set of currently discovered nodes that are not evaluated yet.
// Initially, only the start node is known.
const openSet = [start];
// For each node, which node it can most efficiently be reached from.
// If a node can be reached from many nodes, cameFrom will eventually contain the
// most efficient previous step.
var cameFrom = {};
// For each node, the cost of getting from the start node to that node.
const gScore = dictionary.reduce((acc, word) => { acc[word] = Infinity; return acc }, {})
// The cost of going from start to start is zero.
gScore[start] = 0
while (openSet.length > 0) {
var current = openSet.shift()
if (current == goal) {
return reconstruct_path(cameFrom, current)
}
closedSet[current] = true;
getNeighbors(current).forEach(neighbor => {
if (closedSet[neighbor]) {
return // Ignore the neighbor which is already evaluated.
}
if (openSet.indexOf(neighbor) == -1) { // Discover a new node
openSet.push(neighbor)
}
// The distance from start to a neighbor
var tentative_gScore = gScore[current] + 1
if (tentative_gScore >= gScore[neighbor]) {
return // This is not a better path.
}
// This path is the best until now. Record it!
cameFrom[neighbor] = current
gScore[neighbor] = tentative_gScore
})
}
throw new Error('path not found')
}
function reconstruct_path(cameFrom, current) {
var answer = [];
while (cameFrom[current] || cameFrom[current] == 0) {
answer.push(str.slice(cameFrom[current] + 1, current + 1))
current = cameFrom[current];
}
return answer.reverse()
}
console.log(aStar(START, FINISH));
You could collect all possible combinations of the string by checking the starting string and render then the result.
If more than one result has the minimum length, all results are taken.
It might not work for extrema with string who just contains the same base string, like 'abcabc' and 'abc'. In this case I suggest to use the shortest string and update any part result by iterating for finding longer strings and replace if possible.
function getWords(string, array = []) {
words
.filter(w => string.startsWith(w))
.forEach(s => {
var rest = string.slice(s.length),
temp = array.concat(s);
if (rest) {
getWords(rest, temp);
} else {
result.push(temp);
}
});
}
var string = "ilikealibaba",
words = ["i", "like", "ali", "liba", "baba", "alibaba"],
result = [];
getWords(string);
console.log('all possible combinations:', result);
console.log('result:', result.reduce((r, a) => {
if (!r || r[0].length > a.length) {
return [a];
}
if (r[0].length === a.length) {
r.push(a);
}
return r;
}, undefined))
Use trie data structure
Construct a trie data structure based on the dictionary data
Search the sentence for all possible slices and build a solution tree
Deep traverse the solution tree and sort the final combinations
const sentence = 'ilikealibaba';
const words = ['i', 'like', 'ali', 'liba', 'baba', 'alibaba',];
class TrieNode {
constructor() { }
set(a) {
this[a] = this[a] || new TrieNode();
return this[a];
}
search(word, marks, depth = 1) {
word = Array.isArray(word) ? word : word.split('');
const a = word.shift();
if (this[a]) {
if (this[a]._) {
marks.push(depth);
}
this[a].search(word, marks, depth + 1);
} else {
return 0;
}
}
}
TrieNode.createTree = words => {
const root = new TrieNode();
words.forEach(word => {
let currentNode = root;
for (let i = 0; i < word.length; i++) {
currentNode = currentNode.set(word[i]);
}
currentNode.set('_');
});
return root;
};
const t = TrieNode.createTree(words);
function searchSentence(sentence) {
const marks = [];
t.search(sentence, marks);
const ret = {};
marks.map(mark => {
ret[mark] = searchSentence(sentence.slice(mark));
});
return ret;
}
const solutionTree = searchSentence(sentence);
function deepTraverse(tree, sentence, targetLen = sentence.length) {
const stack = [];
const sum = () => stack.reduce((acc, mark) => acc + mark, 0);
const ret = [];
(function traverse(tree) {
const keys = Object.keys(tree);
keys.forEach(key => {
stack.push(+key);
if (sum() === targetLen) {
const result = [];
let tempStr = sentence;
stack.forEach(mark => {
result.push(tempStr.slice(0, mark));
tempStr = tempStr.slice(mark);
});
ret.push(result);
}
if(tree[key]) {
traverse(tree[key]);
}
stack.pop();
});
})(tree);
return ret;
}
const solutions = deepTraverse(solutionTree, sentence);
solutions.sort((s1, s2) => s1.length - s2.length).forEach((s, i) => {
console.log(`${i + 1}. ${s.join(' ')} (${s.length - 1} spaces)`);
});
console.log('pick no.1');
var arr = ['test0','test2','test0'];
Like the above,there are two identical entries with value "test0",how to check it most efficiently?
If you sort the array, the duplicates are next to each other so that they are easy to find:
arr.sort();
var last = arr[0];
for (var i=1; i<arr.length; i++) {
if (arr[i] == last) alert('Duplicate : '+last);
last = arr[i];
}
This will do the job on any array and is probably about as optimized as possible for handling the general case (finding a duplicate in any possible array). For more specific cases (e.g. arrays containing only strings) you could do better than this.
function hasDuplicate(arr) {
var i = arr.length, j, val;
while (i--) {
val = arr[i];
j = i;
while (j--) {
if (arr[j] === val) {
return true;
}
}
}
return false;
}
There are lots of answers here but not all of them "feel" nice... So I'll throw my hat in.
If you are using lodash:
function containsDuplicates(array) {
return _.uniq(array).length !== array.length;
}
If you can use ES6 Sets, it simply becomes:
function containsDuplicates(array) {
return array.length !== new Set(array).size
}
With vanilla javascript:
function containsDuplicates(array) {
return array
.sort()
.some(function (item, i, items) {
return item === items[i + 1]
})
}
However, sometimes you may want to check if the items are duplicated on a certain field.
This is how I'd handle that:
containsDuplicates([{country: 'AU'}, {country: 'UK'}, {country: 'AU'}], 'country')
function containsDuplicates(array, attribute) {
return array
.map(function (item) { return item[attribute] })
.sort()
.some(function (item, i, items) {
return item === items[i + 1]
})
}
Loop stops when found first duplicate:
function has_duplicates(arr) {
var x = {}, len = arr.length;
for (var i = 0; i < len; i++) {
if (x[arr[i]]) {
return true;
}
x[arr[i]] = true;
}
return false;
}
Edit (fix 'toString' issue):
function has_duplicates(arr) {
var x = {}, len = arr.length;
for (var i = 0; i < len; i++) {
if (x[arr[i]] === true) {
return true;
}
x[arr[i]] = true;
}
return false;
}
this will correct for case has_duplicates(['toString']); etc..
var index = myArray.indexOf(strElement);
if (index < 0) {
myArray.push(strElement);
console.log("Added Into Array" + strElement);
} else {
console.log("Already Exists at " + index);
}
You can convert the array to to a Set instance, then convert to an array and check if the length is same before and after the conversion.
const hasDuplicates = (array) => {
const arr = ['test0','test2','test0'];
const uniqueItems = new Set(array);
return array.length !== uniqueItems.size();
};
console.log(`Has duplicates : ${hasDuplicates(['test0','test2','test0'])}`);
console.log(`Has duplicates : ${hasDuplicates(['test0','test2','test3'])}`);
Sorting is O(n log n) and not O(n). Building a hash map is O(n). It costs more memory than an in-place sort but you asked for the "fastest." (I'm positive this can be optimized but it is optimal up to a constant factor.)
function hasDuplicate(arr) {
var hash = {};
var hasDuplicate = false;
arr.forEach(function(val) {
if (hash[val]) {
hasDuplicate = true;
return;
}
hash[val] = true;
});
return hasDuplicate;
}
It depends on the input array size. I've done some performance tests with Node.js performance hooks and found out that for really small arrays (1,000 to 10,000 entries) Set solution might be faster. But if your array is bigger (like 100,000 elements) plain Object (i. e. hash) solution becomes faster. Here's the code so you can try it out for yourself:
const { performance } = require('perf_hooks');
function objectSolution(nums) {
let testObj = {};
for (var i = 0; i < nums.length; i++) {
let aNum = nums[i];
if (testObj[aNum]) {
return true;
} else {
testObj[aNum] = true;
}
}
return false;
}
function setSolution(nums) {
let testSet = new Set(nums);
return testSet.size !== nums.length;
}
function sortSomeSolution(nums) {
return nums
.sort()
.some(function (item, i, items) {
return item === items[i + 1]
})
}
function runTest(testFunction, testArray) {
console.log(' Running test:', testFunction.name);
let start = performance.now();
let result = testFunction(testArray);
let end = performance.now();
console.log(' Duration:', end - start, 'ms');
}
let arr = [];
let setSize = 100000;
for (var i = 0; i < setSize; i++) {
arr.push(i);
}
console.log('Set size:', setSize);
runTest(objectSolution, arr);
runTest(setSolution, arr);
runTest(sortSomeSolution, arr);
On my Lenovo IdeaPad with i3-8130U Node.js v. 16.6.2 gives me following results for the array of 1,000:
results for the array of 100,000:
Assuming all you want is to detect how many duplicates of 'test0' are in the array. I guess an easy way to do that is to use the join method to transform the array in a string, and then use the match method.
var arr= ['test0','test2','test0'];
var str = arr.join();
console.log(str) //"test0,test2,test0"
var duplicates = str.match(/test0/g);
var duplicateNumber = duplicates.length;
console.log(duplicateNumber); //2