Related
I am working on a practice problem:
Return the length of a string without using javascript's native string.length method.
The only ways I could think of would be substring or slice, but I'm stumped.
You can loop over the string, testing to see whether there is a non-undefined value at each index (as soon as you get an undefined value you've run past the end of the string):
function strLength(s) {
var length = 0;
while (s[length] !== undefined)
length++;
return length;
}
console.log(strLength("Hello")); // 5
console.log(strLength("")); // 0
(I'm assuming that if you're not allowed to use the native string .length property that you probably shouldn't use the array .length property either with str.split("").length...)
Given that this is a practice problem, I suspect the OP may not want ES6/ES2015, but, just in case that's an option, and/or for whoever else is looking at this, here's a concise modern approach:
const str = "Hello world!";
console.log([...str].reduce(a => a+1, 0));
(When I posted this, no other answer had proposed this solution. However, I had missed the fact that #MarkoGrešak had essentially proposed this exact solution in a comment to another question.)
You can use spread element, Array.prototype.keys() iterator, Array.prototype.pop()
var str = "abc";
var len = [...[0,...str].keys()].pop();
console.log(len, str.length);
The briefest have been able to achieve so far using Object.keys(), Array.prototype.pop() and checking for empty string. Approach could probably be improved further.
var len = str === "" ? 0 : +Object.keys(str).pop()+1;
#nnnnnnn utilizes the two methods at above far exceeding the initial attempt in brevity and addressing case of empty string.
var len = +Object.keys(str+' ').pop();
One way would be iterating through a split string like so:
var count = 0;
Array.from("string here".split("")).forEach(function(){count++});
Tip from Marko below in the comments to use the reduce function to shorten it to:
var count = Array.from("string here".split("")).reduce(function(count){return count+1}, 0);
You could use array.length so you answer the question not using the native string.length.
var Str = "Hello world!";
const CountAr = Str.split("").length;
console.log(CountAr);
/*12*/
function stringLength(str) {
var count = 0;
var index = 0;
while(string[index] !== undefined){
count += 1;
index += 1;
}
return count;
}
I think this will work. If you start with '', it won't go into the while loop, and you'll just return 0.
function getStringLength(string) {
var idx = 0;
while (string[idx] !== undefined) {
idx += 1;
}
return idx;
}
This will work.
function length(str) {
str = str.split('');
var length = 0;
str.forEach(function(element) {
length++;
});
return length;
}
length('hello'); // output 5
Yet another way to do it
function getStringLength(str){
var count = 0;
for(var letter in str){
count += 1;
}
return count;
}
console.log(getStringLength('Mississippi')) // 11
console.log(getStringLength('')) // 0
The for in loop is the way to go I think. You can use slice or substring but for in loops can count strings easily too.
function getStringLength(string) {
var length = 0;
for (var i in string){
length++;
}
return length;
}
This is the solution I came up with
I have used a while loop for getting the length of the input
Sharing Two approaches with a while loop
Approach no 1
function getLength(input) {
if(!input){
return 'please provide input'
}
let i = 0;
while (true) {
if (input[i]) {
i += 1
}else{
break
}
}
return i
}
console.log(getLength([1, 5, 3, 7, 8])) // 5
console.log(getLength("Hare Krishna")) // 12
Output
5 (for array)
12 (for string)
Approach no 2
function getLength(input){
let i = 0;
while(input[i] !== undefined){
i++;
}
return i
}
console.log(getLength([1,2,3,48,8,9])) // 6
Output
6 (for array)
function getStringLength(string) {
// Do NOT use any native 'length' methods.
// You might consider using 'substring' or 'slice' as alternatives.
let i = 0;
while (Number(string.slice(i, i+1)) !== 0) {
i++;
} return i;
}
var output = getStringLength('hello');
console.log(output); // --> 5
I have an array that shows this value "135_1,undefined,undefined"
I have to find the "undefined" in the above array and then replace it with "0_0".Undefined can occur multiple times in the array.
I used
var extra = myVariable.replace("undefined", "0_0");
alert(extra);
but then I have to use this three times so that every single time it can search one and replace it.
I have also used this::
for (var i = 0; i < myVariable.length; i++) {
alert(myVariable[i]);
myVariable[i] = myVariable[i].replace(/undefined/g, '0_0');
}
alert(myVariable);
but it did'nt solved my purpose.
String.prototype.replace is a method accessible to strings. undefined is not a string.
This might help you.
for (var i=0, len=arr.length; i<len; i++) {
if (arr[i] === undefined) {
arr[i] = "0_0";
}
}
alert(JSON.stringify(arr));
You could also use Array.prototype.map for this. Note, it only works in IE >= 9
arr = arr.map(function(elem) {
return elem === undefined ? "0_0" : elem;
});
Since the question is tagged with jquery you can use $.map():
var extra = $.map(myVariable, function(item) {
return item || '0_0';
}
This will return a new array whereby each item comprising (in your case) an empty string or undefined is replaced by '0_0'.
var arr = ['135_1',undefined,undefined];
while(arr.indexOf(undefined) != -1) {
pos=arr.indexOf(undefined);
arr[pos]='0_0';
}
Starting with an array of objects:
var array=[
{name:"name1",value:"value1"},
{name:"nameToChange",value:"oldValue"},
{name:"name3",value:"value3"}
];
How do change the value of a given property of one of the objects when another given property in the object is set to a given value?
For instance, starting with my array shown above, I wish to change value to "newValue" when name is equal to "nameToChange".
var array=[
{name:"name1",value:"value1"},
{name:"nameToChange",value:"newValue"},
{name:"name3",value:"value3"}
];
PS. To create the initial array, I am using jQuery's serializeArray(), and I do not wish to change the value of <input name="nameToChange">. I suppose I can change its value, use serialArray(), and then change it back, but this sounds more complicated than necessary.
The easiest way is to iterate over this array:
var i = arr.length;
while (i--) {
if (arr[i].name === 'nameToChange') {
arr[i].value = 'newValue';
break;
}
}
You won't be able to do the same stuff with native 'indexOf', as objects are to be compared.
for (var i = 0; i < array.length; i++) {
if (array[i].name == 'nameToChange') {
array[i].value = 'value';
break;
}
}
fiddle Demo
You need to go through all the elements and search for the required one and then replace with the value.
for(var i = 0; i < array.length; i++){
if(array[i]["name"] == str) {
array[i]["value"] = newValue;
break;
}
}
It's 2013; skip all the messy for loops and use forEach. It's much simpler and semantically cleaner:
array.forEach(function (e) {
if (e.name == 'nameToChange')
e.value = 'newValue';
})
Since you are using jQuery, you could use this:
$.each(array, function () {
if(this.name == 'nameToChange') this.value = 'value';
});
Fiddle
Bear in mind, I don't quite have the vocabulary yet to know what keywords to search for (just jumping on the coding bandwagon now...), so this might be a really easy question to answer!
I have an array of objects, say
M = [A_1, A_2, ..., A_n]
, where A_i is an instantiation of the class
A = {text: "string", coords:[x,y]}
My question is: what is the quick, elegant, simple way of checking whether my array M contains an object A_i where
A_i.text="your mom" && A_i.coords = [9,9]
is true?
I've got access to underscore.js which seems to have some nifty ways of doing things, but I'm a little confused on how to implement it...
Something I've tried (with the underscore.js library) is:
var isitso = _.find(M, function (i) {
return i.text == "your mom" && i.coords == [9,9];
});
At this stage of learning JS, I would appreciate as many different ways of solving this problem. Just to see what can be done and how.
Thanks in advance!
The difficultly with what you have is that array equality is reference equality (they have to be the same memory location), not value equality (they have the same values). If you change your check to:
return i.text == 'your mom' && i.coords[0] == 9 && i.coords[1] == 9;
it should work. In this case you're check whether the first (0) and second (1) elements have the requisite values not comparing the array objects themselves. Comparing numbers does compare values rather than references.
You can't check arrays for equality. You need to do something like:
_.find(M, function (i) {
return i.text == "your mom" && i.coords[0] == 9 && i.coords[1] == 9;
});
Never heard of underscore js, so I cannot speak to its details. Most javacript frameworks have a foreach method of one type or another, to emulate the not-yet-standardized foreach loop.
function findMatches(/* target array*/ target, /* matching function*/ match) {
var dummy = [];
dojo.forEach(target, function(t) {
if (match(t)) {
dummy.push(t);
}
});
return dummy;
}
var allMatches = findMatches(M, function (m) {
m.text == "your mom" && m.coords == [9,9]
});
Note that dojo.forEach is the forEach in the Dojo library I use. jQuery also contains such a thing of your preferred library does not.
Its late, I haven't put this code in an actual browser, but the idea is sound, even if I made a typo.
Use _.filter method.
var filtered = _.filter(M, function(i) { return (i.text == "text2" && i.cords[0] == 3 && i.cords[1] == 4) });
All of the other answers so far are using third-party js libraries. The following is an attempt at a straight js solution. Fiddle: http://jsfiddle.net/rNfph/
var M = [
{text:'one', coord: [0,0]},
{text:'two', coord: [1,1]},
{text:'three', coord: [2,2]},
{text:'four', coord: [3,3]},
{text:'five', coord: [4,4]},
{text:'six', coord: [5,5]},
{text:'seven', coord: [6,6]},
{text:'eight', coord: [7,7]},
{text:'nine', coord: [8,8]},
{text:'ten', coord: [9,9]}
];
var search = function(str, x, y){
for(var i=0, len=M.length; i<len; i++){
if( M[i].text === str && M[i].coord[0] === x && M[i].coord[1] === y ){
return true;
}
}
return false;
}
console.log( search('three', 2, 2) );
console.log( search('three', 1, 2) );
Now, take this with a grain of salt. I am not an expert in complexity. There very well could be better ways to do this since this implementation requires iteration through potentially all of the values.
If there was a restriction on this where the value of 'text' is required to be unique, then instead of using an array, you could structure it all as an object (dictionary) and do the checks without needing any iterations at all.
See this fiddle: http://jsfiddle.net/4mrsh/
var M = {
'one': [0,0],
'two': [1,1],
'three': [2,2],
'four': [3,3]
}
var search = function(key, x, y){
if( !M[key] || !(M[key][0] === x && M[key][1] === y) ) return false;
return true;
}
console.log( search('three',2,2) ); //true
console.log( search('three',1,2) ); //false
if (!Array.prototype.each) {
Array.prototype.each = function(callback) {
var i, l = this.length;
for (i = 0; i < l; i += 1) {
if (callback(i, this[i]) === true) return;
}
}
}
function anMHasYourMom(m) {
var found;
m.each(function(i, el) {
return found = (
el.text === "your mom"
&& el.coords[0] === 9
&& el.coords[1] === 9
);
});
return found;
}
var M = [A_1, A_2, ..., A_n];
if (anMHasYourMom(M)) {
window.alert('It has one!');
}
I have an array of objects that can have up to 6 products in them e.g.
var products = [{name:'Trampoline'}, {name:'Net'}, {name:'Tent'}, {name:'Hoop'}];
// missing Ladder & Anchor
I need a way to check through them, and have it tell me that 'Ladder' and 'Anchor' aren't in the array products. !$.inArray doesn't work (the jquery one).
Can anyone help?? Maybe my brain has just died for the day, cos I just can't figure it out.
I tried starting with an array of all the items it needs, but the first loop through just removes them all becase the first one is not an accessory.
this.getUpsellItem = function() {
var p = this.getProduct();
var slots = ['Net','Tent','Ladder','Basketball','Anchor'];
for(var i = 0; i< p.length; i++) {
if(p[i].display_name2.indexOf('Net') === -1) slots.splice(0,1);
if(p[i].display_name2.indexOf('Tent') === -1) slots.splice(1,1);
if(p[i].display_name2.indexOf('Anchor') === -1) slots.splice(3,1);
if(p[i].display_name2.indexOf('Ladder') === -1) slots.splice(2,1);
if(p[i].display_name2.indexOf('Basketball') === -1) slots.splice(4,1);
console.log(p[i].display_name2.indexOf('Basketball'))
}
console.log('Printing slots')
print_r(slots)
};
Since you're using jQuery we can use the handy jQuery.grep() function to return only the elements in slots that aren't present in products. $.grep takes a function that it uses to filter which elements in the array it should return and which it should discard. In this case we just test each item in slots using products.indexOf. Something like this should suffice:
var slots = [ 'Net', 'Tent', 'Ladder', 'Basketball', 'Anchor' ]
, products = [ { name: 'Trampoline' }, { name: 'Net' },
{ name: 'Tent' }, { name: 'Hoop' }
]
, missing = $.grep(slots, function(product) {
return products.indexOf({ name: product }) < 0 }
)
;
console.log(missing);
Your problem is that you have an array of objects:
var products = [{name:'Trampoline'}, {name:'Net'}, {name:'Tent'}, {name:'Hoop'}];
And you want to search based on a property of these objects. The indexOf method:
compares [...] using strict equality (the same method used by the ===, or triple-equals, operator)
So you won't find what you're looking for unless you have the specific object in hand, just searching based on the property value or an object with the same structure won't work.
jQuery's $.inArray utility function is (AFAIK) just a portability wrapper for JavaScript implementations that don't have an indexOf method in their Array.
You'll need a search function of your own, something like this:
function indexOfByProperty(array, property, value) {
for(var i = 0; i < array.length; ++i)
if(array[i][property] == value)
return i;
return -1;
}
You could also use === if you want to be stricter but that's up to you and what you need the function to do.
If your array is large, you are better off using a map rather than an array
var products = {"Trampoline": {name:'Trampoline'}, "Net": {name:'Net'}, etc..};
products["foo"] returns null
products["Trampoline"] returns {name: 'Trampoline'}
in O(1) time rather than O(n) time
In ES5 you can use Array.some() to drill into nested Objects in an array:
var products = [{name:'Trampoline'}, {name:'Net'}, {name:'Tent'}, {name:'Hoop'}];
var found_ladder = products.some(function(val, idx) {
return val.name === 'Ladder';
});
Javascript in_array function
function in_array (needle, haystack, argStrict) {
// Checks if the given value exists in the array
// * example : in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
// * returns : false
// * example : in_array('van', ['Kevin', 'van', 'Zonneveld']);
// * returns : true
var key = '', strict = !! argStrict;
if (strict) {
for (key in haystack) {
if (haystack[key] === needle) { return true;}
}
} else {
for (key in haystack) {
if (haystack[key] == needle) { return true; }
}
}
return false;
}