I can not finish one of the easiest kata on codewars.
Want to understand where am I wrong!
Instructions: Sum all the numbers of the array except the highest and
the lowest element (the value, not the index!). (The highest/lowest
element is respectively only one element at each edge, even if there
are more than one with the same value!) If array is empty, null or
None, or if only 1 Element exists, return 0.
function sumArray(array) {
var finalSum = 0;
if (array != null || !array) {
for (var i = 0; i < array.length; i++) {
finalSum += array[i];
}
if (array.length === 0 || array.length <= 1) {
return 0;
} else {
return finalSum - Math.max(...array) - Math.min(...array);
}
}
}
Everything seems fine and should work, but it is not passing final tests.
TypeError: Cannot read property 'length' of null
I tried to add in the first if typeof array != 'null', typeof array != 'undefined' but it did not help...
In Javascript, the return of typeof of a null will be an object. That is why your first if doesn't work. You check if its not equal to null and its true, because the return will be object. Read more here ECMAScript null.
More proof on this, pull out a console and type the following.
a = null
typeof array // will return "object"
a != null // will return false, even if we attributed the value of a to null.
a !== null // will false also
a == null // will return true, so let's use this !
I assume that the error you are getting is when the test is sumArray(null) or sumArray(). In order to properly return 0, you have to do this.
function sumArray(array) {
var finalSum = 0;
if (array == null)
return 0;
if (array != null || !array) {
for (var i = 0; i < array.length; i++) {
finalSum += array[i];
}
if (array.length === 0 || array.length <= 1) {
return 0;
} else {
return finalSum - Math.max(...array) - Math.min(...array);
}
}
}
For some weird reason, using a array == null will return the proper return value (true if your array is null). (I haven't read much on why).
if(typeof array !== "undefined" && typeof array !== "null" )
You can try this.
check like this.
if(array && array.length) {
for (var i = 0; i < array.length; i++) {
finalSum += array[i];
}
if (array.length === 0 || array.length <= 1) {
return 0;
} else {
return finalSum - Math.max(...array) - Math.min(...array);
}
}
Related
I am trying to code a program that will remove any zeros, empty strings, null, or undefined values in an array. However when I run this array: [1,null,2,3,0,-1,1.1], through the code below it returns the array with the null and 0 value still in the array. Any help?
function cleanArray(arr) {
var i = 0;
for (i; i < arr.length; i++) {
if (arr[i] === 0 || arr[i] === '' || arr[i] === null || arr[i] === undefined) {
arr.splice(i, 1);
i--;
}
return arr;
}
}
Because of return arr;, which you have placed inside your for loop. As soon as the code runs through the first element, it hits the return and leaves the function with the array as it was after the first run of the loop.
Just move the return statement outside the for loop, like so:
function cleanArray(arr) {
var i = 0;
for (i; i < arr.length; i++) {
if (arr[i] === 0 || arr[i] === '' || arr[i] === null || arr[i] === undefined) {
arr.splice(i, 1);
i--;
}
}
return arr;
}
You need to move return arr; outside the for loop.
function cleanArray(arr) {
var i = 0;
for (i; i < arr.length; i++) {
if (arr[i] === 0 || arr[i] === '' || arr[i] === null || arr[i] === undefined) {
arr.splice(i, 1);
i--;
}
}
return arr;
}
Use .filter() and the falsy value to remove the unwanted items
function cleanArray(arr) {
return arr.filter(function (item) {
return !!item;
//or return arr[i] !== 0 && arr[i] !== '' && arr[i] !== null && arr[i] !== undefined
})
}
very simplistically,
arr = arr.filter(function(item) {
return !!item;
});
but that would let true and other non numeric values through
arr = arr.filter(function(item) {
return !!item && !isNaN(item);
});
may work better (haven't tested it myself - leaves you with something to try)
You can make use of array filter
var arr = [1,null,2,3,0,-1,1.1];
var filteredArr = arr.filter(function(i){
// if in javascript checks for truthy values
if(i) {
return i;
}
});
console.log(filteredArr); // [1, 2, 3, -1, 1.1]
Demo here
function cleanArray(arr) {
var i = 0, newArr = [];
for (i; i < arr.length; i++) {
if (arr[i]) {
newArr.push(arr[i]);
}
}
return newArr;
}
This will work for sure. Hope I was helpful.
Here the fiddle: https://jsfiddle.net/rok_ed/coakcd3L/
I have an javascript array and I want to delete an element based on the value of the array, this is my array and this is what I have tried without success.
array = []
array.push (["Mozilla","Firefox",1.10])
index = array.indexOf(["Mozilla","Firefox",1.10])
array.splice(index, 1)
But it doesn't work, any idea¿?
You're trying to compare arrays, which are objects and have unique addresses. Your index variable is -1.
Try ['Mozilla','Firefox',1.10] === ['Mozilla','Firefox',1.10] in your console, you'll see that just because two arrays have the same values, it doesn't mean they are the same array.
What you need is a deep-equals style of comparison, that checks each value in the array, to see if two arrays have a likeness.
Take a look at lodash's isEqual function for an idea.
Here's a simple looping function:
function deepIndex(array, comparison) {
var i, j;
main:
for (i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
for (j = 0; j < array[i].length; j++) {
if (array[i][j] !== comparison[j]) {
continue main;
}
}
return i;
}
}
}
var arr = [];
arr.push('string', ['Mozilla','Firefox',1.10], 'thing');
var index = deepIndex(arr, ['Mozilla','Firefox',1.10])
console.log(index, arr);
arr.splice(index, 1);
console.log(arr);
Take a look at this:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
This is function, made by the Creator of JQUery.
Basically you take the Index of one thing and than it is getting removed
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
//Equals Function taken from:
//http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
array = [];
array.push (["Mozilla","Firefox",1.10]);
array.push (["Microsoft","Spartan",1.0]);
array.push (["Safari","Safari",1.4]);
index = indexOfArr(array,["Mozilla","Firefox",1.10]);
array.remove(index, index);
document.getElementById("length").innerHTML = array.length;
for(var i = 0; i < array.length; i++){
document.getElementById("elems").innerHTML += "<br>"+array[i];
}
function indexOfArr(hay, needle){
for(var i = 0; i < hay.length; i++){
if (hay[i].equals(needle)){
return i;
}
}
return -1;
}
<span id = "length"></span><br>
<span id = "elems">Elements:</span>
You can use the fiter metodh, instead of indexOf.
Within the callback of that method, you can choose different approaches:
Use toString on the arrays and compare the two strings
Test for the length and the content, by iterating over the contained elements
... Continue ...
In any case using === will solve the problem, unless the object contained is exactly the same against which you are trying to match.
By the same, I mean the same. We are non speaking about having the same content, but to be the same instance.
Loop over your array and check the equality:
array = [];
array.push(["Mozilla", "Firefox", 1.10]);
for (var i = 0; i < array.length; i++) {
if (arraysEqual(array[i], ["Mozilla", "Firefox", 1.10])) {
array.splice(i, 1);
}
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a === null || b === null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
JSFiddle: http://jsfiddle.net/ghorg12110/r67jts35/
Based on this question : How to check if two arrays are equal with JavaScript?
You can do something like this
array = []
array.push (["Mozilla","Firefox",1.10])
tempArray = array[0];
index = tempArray.indexOf("Mozilla","Firefox",1.10)
array.splice(index, 1)
You can build on this if you put for loop instead of hard coding.
I understand there are other pages on this but I am trying to get my own working and I do not know why it is not working. I am new to node.js.
for (var index in output)
{
if (opt.options.showEmpty != true)
{
var check = arrayIsEmpty(output[index]);
if ( check == true )
{
continue;
}
else
{
var array = removingEmptyString(output[index]);
console.log(index + "\t" + array);
//console.log(index+ "\t" + output[index]);
}
}
}
function removingEmptyString(array)
{
var newArray;
for( var i = 0; i < array.length; i++)
{
if(array[i] != "" || array[i] != null)
{
newArray[i] = array[i];
}
}
return newArray;
}
My result is tree,,, that i was previously getting before the code i wrote. now i get an error of
newArray[i] = array[i];
^
TypeError: Cannot set property '0' of undefined
at removingEmptyString (librarySeeker.js:130:18)
at result (librarySeeker.js:76:19)
at /async/lib/async.js:226:13
at async/lib/async.js:113:25
at async/lib/async.js:24:16
at async/lib/async.js:223:17
at /async/lib/async.js:510:34
at IncomingMessage.<anonymous> (pull.js:295:10)
at IncomingMessage.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:910:16
You could just use the .filter method in Array's prototype.
var pirate = ['a','1','',0];
function arr (value) {
return value.filter(function (item) {
return item !== '';
});
}
arr(pirate);
// <- ['a','1',0]
As an alternative, you might want to consider naming the callback to .filter
var pirate = ['a','1','',0];
function worthy (value) {
return value !== '';
}
pirate.filter(worthy);
// <- ['a','1',0]
In the spirit of learning, here is a working version of your solution:
function removingEmptyString(array) {
'use strict';
var newArray = []; // don't forget to initialize it
for( var i = 0, len = array.length; i < len; i += 1) {
if(typeof array[i] === 'string' && array[i].length > 0) {
// add the string to the end of the new array
newArray.push(array[i]);
}
}
return newArray;
}
The error is saying that newArray has not been initialised, so it cannot assign the 0 property to an undefined object.
You can improve your function to make it work:
function removingEmptyString(array){
var newArray = [];
for( var i = 0; i < array.length; i++){
// empty string and null are falsy values by default is js
if(array[i])
{
// use this if you want to keep "undefined" values in the newArray in place
// of the null ones in the original array
newArray[i] = array[i];
// otherwise just push the values in the new array
// newArray.push(array[i]);
}
}
return newArray;
}
it looks like easy but I kind of stuck in trying to figure out how to filter data before pushing json data into javascript array.
//push data into javascript array [timestamp,value]
dataJSON2 = [];
for (i in parsed2) {
if (parsed2[i].value == 'open' || parsed2[i].value == 'true' ) {
thevalue = 1;
} else if (parsed2[i].value == 'closed' || parsed2[i].value == 'false' ) {
thevalue = 0;
} else {
thevalue = parsed2[i].value;
}
dataJSON2.push( [ (parsed2[i].timestamp),
parseFloat (thevalue) ] );
}
what I am trying to accomplish is if current thevalue var is the same with the previous thevalue then it would discard the data and go to the next i until it return different value.
It would be easy if using for looping but I don't know different way to push json object rather than for..in, nor to use filtering i value before pushing it.
var dataJSON2 = [], previous;
for (i in parsed2) {
if (parsed2[i].value === 'open' || parsed2[i].value === 'true' ) {
thevalue = 1;
} else if (parsed2[i].value === 'closed' || parsed2[i].value === 'false' ) {
thevalue = 0;
} else {
thevalue = parsed2[i].value;
}
if (previous === thevalue) continue;
previous = thevalue;
dataJSON2.push( [ (parsed2[i].timestamp), parseFloat (thevalue) ] );
}
This would check for previous value with the current value and skip it if they are same
dataJSON2 = [];
var lastVal = parsed2 && parsed2[0];
for (var i = 1; i < parsed2.length; i++) {
if (lastVal !== parsed2[i].value) {
dataJSON2.push([(parsed2[i].timestamp), parseFloat(parsed2[i].value)]);
lastVal = parsed2[i];
}
}
Extracted from Array.indexOf from MDN
Create a function like this
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
'use strict';
if (this == null) {
throw new TypeError();
}
var n, k, t = Object(this),
len = t.length >>> 0;
if (len === 0) {
return -1;
}
n = 0;
if (arguments.length > 1) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
for (k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
};
}
and use indexOf like this
if (dataJSON2.indexOf( [ (parsed2[i].timestamp), parseFloat (thevalue) ] ) == -1){
dataJSON2.push( [ (parsed2[i].timestamp), parseFloat (thevalue) ] );
}
I used the code described here but now, when I do a "for ... in ..." cicle, it gets the function "indexOf" as an index position of the array...
Example Code:
var the_array=new Array();
for (key in the_array){
console.log(key +" - "+the_array[key]);
}
This code shows this in the console:
indexOf - function (searchElement /*, fromIndex */ ) {
"use strict";
if (this == null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n != n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n != 0 && n != Infinity && n != -Infinity) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
}
How could I prevent the function from appearing as a key on the array?
Btw, I know that I can use the inArray function of jquery but, in this case, I would like to use the "indexOf" function...
It's a bad idea to use for...in on arrays, for this and other reasons. See my answer here:
Why is 'for(var item in list)' with arrays considered bad practice in JavaScript?