I am a coding beginner and I was writing the following function that checks if the next string of a given array is one unit longer:
function canBuild(arr) {
for(let i = 0; i < arr.length; i++) {
if (i == arr.length-1) { return true }
if (arr[i].length+1 != arr[i+1].length) { return false }
}
}
desired output:
canBuild(["a", "at", "ate", "late", "plate", "plates"]) ➞ true
canBuild(["it", "bit", "bite", "biters"]) ➞ false
// "biters" is 2 units longer than the previous string
I was wondering if there is a more efficient and shorter way to write the same function, if someone explained me other ways to do so I would really appreciate it!
Use every method and some temp variable (x here)
const canBuild = (arr) => (
(x = arr[0]?.length), arr.every((c) => c.length === x++)
);
console.log(canBuild(["a", "at", "ate", "late", "plate", "plates"]));
console.log(canBuild(["it", "bit", "bite", "biters"]));
function canBuild(arr) {
for(let i = 0; i < arr.length; i++) {
if(i+1 != arr[i].length)
return false;
}
return true;
}
This is a O(n) solution.
function canBuild(arr) {
for(let i = 0; i < arr.length; i++) {
if(i > 0 && arr[i].length !== arr[i-1].length+1)
return false;
}
return true;
}
EDIT: even better, as suggeste by Thomas:
function canBuild(arr) {
for(let i = 1; i < arr.length; i++) {
if(arr[i].length !== arr[i-1].length+1)
return false;
}
return true;
}
Related
function confirmEnding(str, target) {
var end = target;
var match = '';
for(var x = 0; x < str.length; x++){
for(var j = 0; j < str[x].length; j++){
if(str[x][j]){
match = str[x][j];
}
}
}
return match.substr(-target.length) === target;
}
confirmEnding("He has to give me a new name", "name");
but I want to know if I can instead loop through the string and then check it using the appropriate indexes.
Can someone understand my approach and let me know how/why it's not doable?
It's currently only checking for the last character, so whole words aren't working. I know the line below will work
return str.substr(-target.length) === target;
will work, but can someone help me with my approach
Edit:
I changed it more slightly, and got closer but still no luck.
function confirmEnding(str, target) {
for(var x = str.length-1; x < str.length; x++){
for(var j = target.length-1; j>=0; j--){
if(str[x] === target[j]){
return true;
} else{
return false;
}
}
}
}
confirmEnding("Walking on water and developing software from a specification are easy if both are frozen", "specification");
That returns true, when it should return false. I see why, but thinking of a resolve.
If using the loop is a strict requirement, then I would do it in a way
function confirmEnding(source, target) {
var lengthT = target.length;
var lengthS = source.length;
for(var x = 0; x < lengthT; x++) {
if(source[lengthS - 1 - x] !== target[lengthT - 1 - x]) {
return false;
}
}
return true;
}
confirmEnding("He has to give me a new name", "name"); // true
But the easier implementation of confirmEnding method would be just
function confirmEnding(source, target) {
return source.substr(source.length - target.length, target.length) === target;
}
I hope everyone is having a good day.
This is my first ever post on Stackoverflow!
I have just completed the javascript course on codeacademy and have read a couple of books on it too. Now I am on codewars. I would classify myself as a beginner in Javascript.
I find myslef a little stuck on a challenge, please can someone shed some light on what I may be doing wrong? Many thanks in advance!
Here is the instructions:
Check to see if a string has the same amount of 'x's and 'o's. The method must return a boolean and be case insensitive. The string can contains any char.
And here is my code:
function XO(str) {
var x = [];
var o = [];
for (var i = 0; i <= str.length; i++) {
if (str(i).toLowerCase === "x") {
x.push(i);
} else if (str(i).toLowerCase === "o") {
o.push(i);
}
if (x.length === o.length) {
return true;
} else {
return false;
}
}
}
i corrected mistakes and use code comment to explain
function XO(str) {
var x = [];
var o = [];
for (var i = 0; i < str.length; i++) { // i must be lower than length
// str[i] or str.charAt(i), not str(i)
if (str[i].toLowerCase() === 'x') { // toLowerCase is function, it must be called with toLowerCase()
x.push(str[i]); // should push character
} else if (str[i].toLowerCase() === 'o') {
o.push(str[i]);
}
}
// return statement must be located at the end
if (x.length == o.length) {
return true;
} else {
return false;
}
}
console.log(XO('xo'));
console.log(XO('xxo'));
console.log(XO('xoX'));
console.log(XO('xoOX'));
function XO(str) {
var x = 0, // numbers are better
o = 0;
for (var i = 0; i < str.length; i++) { // changed from '<=' to '<'
if (str[i].toLowerCase() === "x") {
x++;
} else if (str[i].toLowerCase() === "o") {
o++;
}
}
return x === o;
}
str.match(/x/g).length==str.match(/o/g).length
function checkIfOequalsX(str){
return str.match(/x/g).length==str.match(/o/g).length
}
console.log(checkIfOequalsX('xxooxo'));
console.log(checkIfOequalsX('xxooxoo'));
you can do it with
str.match(/x/g).length==str.match(/o/g).length
The third if else will never be executed because for a string there will be always a value.
If you want to return the count then the check of length should be performed after the for loop.
var xCount = 0; var oCount = 0;
for (var i = 0; i < str.length; i++) {
if (str[i].toLowerCase() === "x") {
xCount++;
} else if (str[i].toLowerCase() === "o") {
oCount++;
}
}
return xCount === oCount;
About another solutions containing the check based on str.match method, the complexity of using that piece of code is twice compared to above because the str.match loop is performed twice to match both the strings.
function XO(str) {
let strn = str.toLowerCase();
let countX = [];
let countO = [];
for(let i=0; i<strn.length; i++) {
if(strn[i] == 'x') {
countX.push(strn[i])
} else if(strn[i] == 'o') {
countO.push(strn[i])
}
}
if(countX.length == countO.length){
return true
} else if(countX.length !== countO.length) {
return false
}
}
You can use the Regex for finding those characters:
function XO(str) {
return str.match(/o/ig).length === str.match(/x/ig).length;
}
function XO(str) {
let letraO = 0
let letraX = 0
const myArray = str.toLowerCase();
for (i=0; i<myArray.length; i++){
myArray[i] === 'o'? letraO++ : letraX ++
}
return letraO===letraX? true : false
}
function XO(str) {
// make the string lowercase because we are case insensitive
str = str.toLowerCase();
// put the string into an array
var arrayOfCharacters = str.split("");
//count the x's
var countX = arrayOfCharacters.reduce( function( n, val ) {
return n + (val === 'x');
}, 0);
// count the o's
var countO = arrayOfCharacters.reduce( function( n, val ) {
return n + (val === 'o');
}, 0);
// do these numbers match? if so return true and if not return false
if ( countX == countO ) {
return true;
} else {
return false;
}
}
I make a function used to return string with string value like this: "not aritmatic". But when I recursive my function to controll another action, my recursive function not work. how to doing recursive correctly in javascript?
//call function ArithGeo
ArithGeo([2, 4, 6, 8, 12]);
//build function ArithGeo
function ArithGeo(arr) {
var copy_arr = arr;
var array_selisih = [];
for (i = 0; i <= arr.length - 1; i++) {
array_selisih[i] = arr[i + 1] - arr[i];
}
var j = 0;
var x = array_selisih[0];
if (arr.length % 2 == 1) {
for (j = 0; j <= array_selisih.length - 2; j++) {
//alert(array_selisih[x]+":"+array_selisih[j]);
if (array_selisih[x] != array_selisih[j]) {
return 'notaritmatic';
}
}
} else if (arr.length % 2 == 0) {
for (j = 0; j <= array_selisih.length - 3; j++) {
// alert(array_selisih[x]+":"+array_selisih[j]);
if (array_selisih[x] != array_selisih[j]) {
return 'notaritmatic';
}
}
}
return "aritmatik";
//my problem is here
if (ArithGeo(copy_arr) == "notaritmatic") {
//do something when return value is not aritmatic string
alert('not aritmatic ok');
}
}
I am sorry if my algorithm is long, I just try to sharpen my skill to solve problem with own idea. -_-
https://jsfiddle.net/fwdgmvyw/
This question already has answers here:
Remove duplicate values from JS array [duplicate]
(54 answers)
Closed 8 years ago.
I have the following script that's supposed to uniqualize array:
function uniques(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
However, when it receives only one element, it just breaks it into the letters (which is understandable).
Do you know how I make it check if it's receiving only one element and then returns it back?
Thanks!
I'm not sure why you need the nested loop - you only need a single loop if you're processing a non-nested array:
function uniques(arr) {
if (arr.length === 1) { return arr };
var a = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (a.indexOf(arr[i]) === -1) {
a.push(arr[i]);
}
}
return a;
}
DEMO
If you want to process nested arrays, use a recursive function. Here I've used underscore's flatten method as the basis:
function toType(x) {
return ({}).toString.call(x).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
function flatten(input, output) {
if (!output) { output = []; }
for (var i = 0, l = input.length; i < l; i++) {
var value = input[i];
if (toType(value) !== 'array' && output.indexOf(value) === -1) {
output.push(value);
} else {
flatten(value, output);
}
}
return output.sort(function (a, b) { return a - b; });
};
var arr = [1, 2, 3, [[4]], [10], 5, 1, 3];
flatten(arr); // [ 1, 2, 3, 4, 5, 10 ]
DEMO
I think the solution is this:
function uniques(arr) {
if (arr.length > 1) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
else
{
return arr;
}
}
What you're trying to do is a linear search on the created matrix for each item in the original one.
The solution below will accomplish this, but at a great cost. If your original matrix is 50x50 with unique values in each cell, it will take you 50^3 (=125000) loops to exit the function.
The best technique to search, in programming science, takes O(log(N)) that means that if you'll use it on your problem it will take log(50^2) (=11) loops.
function uniques(arr) {
var items = [];
var a = arr.map(function(row, i) {
return row.map(function(cell, j) {
if (items.indexOf(cell) >= 0) {
items.push(cell);
return cell;
}
});
});
}
I need to search for the presence of an array inside an array. It is similar to jQuery.inArray function.
For
var a = [ [1,2], [1,3] ];
console.log( jQuery.inArray([1,3],a ) )
I get -1 as ans. How to do this?
Thank you
In V8 (that is, Chrome), there is a nifty trick: while == does not work for arrays, <= && >= does.
You can iterate and check for each item if it's appearent:
for(var i = 0; i < a.length; i++) {
if(a[i] >= [1, 3] && a[i] <= [1, 3]) alert(i);
}
For other browsers, you'd need a function that checks for array equality:
http://www.svendtofte.com/code/usefull_prototypes/prototypes.js
Array.prototype.compareArrays = function(arr) {
if (this.length != arr.length) return false;
for (var i = 0; i < arr.length; i++) {
if (this[i].compareArrays) { //likely nested array
if (!this[i].compareArrays(arr[i])) return false;
else continue;
}
if (this[i] != arr[i]) return false;
}
return true;
}
Then:
for(var i = 0; i < a.length; i++) {
if(a[i].compareArrays([1, 3])) alert(i);
}
function inArray (needle, haystack) {
for (var idx in haystack) {
if (haystack[idx].join(',') == needle.join(','))
return idx;
}
return -1;
}
try this
function look4arr(arr, v) {
for (var i = 0, l = arr.length; i < l; i += 1) {
if (arr[i].toString() === v.toString()) { //or use +''
return true;
}
}
return false;
}
var a = [[1,2], 2],
ok = [1,2],
ko = [2,3]
look4arr(a, ok); // true
look4arr(a, ko); // false
// as far as the array you are looking at contains primitives seem to work fine
if you need to search for something "more" ...I mean object literals, regexp, functions
You could use a function similar to the following one
function look4x(arr, v) {
for (var i = 0, isObjOrArray = false, l = arr.length; i < l; i += 1) {
isObjOrArray = {}.toString.call(arr[i]).match(/\[object\s(Array|Object)\]/);
if (
(isObjOrArray && JSON.stringify(arr[i])+'' == JSON.stringify(v)+'' )
||
(!isObjOrArray && arr[i].toString() === v.toString())
) {
return true;//or i if a jQuery.inArray output is needed
}
}
return false; // or -1 ... if ... jQuery.inArray
}
var a = [
[1,[1,[1,[1,2]]]],
2,
true,
'hei',
Infinity,
{"o" : "s", 'd':[1,2,3]},
new RegExp(/\s/),
function(){alert('hei');}
],
ok = [1,[1,[1,[1,2]]]];
alert(
look4x(a, [1,[1,[1,[1,2]]]])
&&
look4x(a, true)
&&
look4x(a, 'hei')
&&
look4x(a, Infinity)
&&
look4x(a, {"o" : "s", 'd':[1,2,3]})
&&
look4x(a, new RegExp(/\s/))
&&
look4x(a, function(){alert('hei');})
); // true, in this case
Please note that I didn`t tested it yet with a complete test; I'll post a test asap
Event if I seem to be late, hope it can help someone.
Bye