I've the following implementation.
Array.prototype.abc = function(condition, t){
var arr = [];
for( var i = 0; i < this.length; i++){
arr.push(condition(this[i],t));
}
return arr;
};
var a = [1,2,3,4];
var t = 2;
alert(a.abc( function(item,diviser){
if(item % diviser === 0) { return item; }
},t));
The result should be [2,4]. Instead I'm getting [,2,,4].
I've tried the following conditions but it always returns the above result.
if(condition(this[i],t) !== false){ arr.push(condition(this[i],t)); }
This I'm doing when I do
if(item % diviser === 0) { return item; } else { return false; }
The false condition doesnot work for 'false' or true or 'true' or for that matter any value I return in else part. In the actual implementation I do not have the else part though. I know we can use splice or something to remove the blank sections. But I do not understand even if i don't return anything why blank in being created. And even after using if condition before arr.push it does not work. What exactly is happening and how to remove the blanks in the array?
You have to check whether the returned value is undefined or not from your callBack,
for( var i = 0; i < this.length; i++){
var x = condition(this[i],t);
if(typeof x !== "undefined") arr.push(x);
}
You have made 2 different attempts to fix this but that will fail because,
!== false, your callBack will return either a number or undefined. So the strict equality will fails all the time and will be evaluated to false always since the operand's types are different.
if(item % diviser === 0) { return item; } else { return false; } This will return false when the condition fails and hence false will be pushed into the array. And it will not skip that pushing part.
Move the cmondition outside of the push and place it before. The condition should only return true or false.
condition(this[i],t) && arr.push(this[i]);
This is because you are doing a push regardless of what condition is returning.
Replace this
arr.push(condition(this[i],t));
with
var val = condition(this[i],t)
val = val !== false && arr.push(val);
Since your condition method is explicitly returing false, you can simply check for val !== false
DEMO
Array.prototype.abc = function(condition, t){
var arr = [];
for( var i = 0; i < this.length; i++){
var val = condition(this[i],t); console.log(val);
val !== false && arr.push(val);
}
return arr;
};
var a = [1,2,3,4];
var t = 2;
document.body.innerHTML += a.abc( function(item,diviser){
if(item % diviser === 0) { return item; } else { return false; }
},t);
Related
I wrote a simple function checking if an array contains duplicates, I want it to return true if it does and false if it doesn't.
function containsDuplicates(a) {
var hash = {};
a.forEach((elem, index) => {
if (hash[elem] === undefined) {
hash[elem] = 1;
} else {
console.log('true')
return true;
}
if (index === a.length - 1) {
console.log('false')
return false;
}
})
}
var arr = [1, 2, 3, 4];
containsDuplicates(arr)
My console.log logs just fine but it doesn't seem to be hitting the return. My entire function returns undefined every time. Why is this the case?
You are returning from the callback that you passed to forEach().
You are returning from the callback you passed to foreach. You should try something like this instead.
function hasDuplicates(array) {
var keyStore = {};
for (var i = 0; i < array.length; ++i) {
var value = array[i];
if (value in keyStore) {
return true;
}
keyStore[value] = true;
}
return false;
}
It's about a basic algorithm challenge, in which the user has to return true if the string in the first element of the array contains all of the letters of the string in the second element of the array, e.g.:
["hello", "Hello"] should return true.
["Alien", "line"] should return true.
So far, I've tried this:
function mutation(arr) {
var value1 = arr[0].toLowerCase();
var value2 = arr[1].toLowerCase();
for (var i = 0; i < value2.length; i++) {
if (value1.indexOf(value2.charAt(i)) !== -1)
return true;
else
return false;
}
}
}
mutation(["hello", "hey"]);
While passing the value mutation(["hello", "hey"]), it isn't returning false.
it looks like youre pretty close, except you seem to be returning true early. Instead, if the indexOf returns -1 break from the loop and return false, otherwise let the loop run to completion and return true afterward (since it didnt return early, we know all chars are present)
function mutation(arr) {
var value1 = arr[0].toLowerCase();
var value2 = arr[1].toLowerCase();
for(var i=0;i<value2.length;i++){
if(value1.indexOf(value2.charAt(i)) === -1) { return false; }
}
return true;
}
mutation(["hello", "hey"]);
Check this out:
function mutation(arr) {
var value1 = arr[0].toLowerCase();
var value2 = arr[1].toLowerCase();
var result = true;
for (var i = 0; i < value2.length; i++) {
if (value1.indexOf(value2.charAt(i)) === -1)
result = false;
}
alert(result);
}
mutation(["Alien", "line"]);
mutation(["hello", "Hello"]);
mutation(["hello", "hey"]);
Plunker: https://plnkr.co/edit/csauovjhFeFltkbqRxjx?p=preview
I'm trying to work out how to match arrays that share the same elements, but not necessarily in the same order.
For example, these two arrays share the same set of elements, even though they're in a different order.
Is there any way to determine whether two arrays contain the same elements?
var search1 = ["barry", "beth", "debbie"];
var search2 = ["beth", "barry", "debbie"];
if (search1 == search2) {
document.write("We've found a match!");
} else {
document.write("Nothing matches");
}
I've got a Codepen of this running at the moment over here: http://codepen.io/realph/pen/grblI
The problem with some of the other solutions is that they are of O(n²) complexity, if they're using a for loop inside of a for loop. That's slow! You don't need to sort either—also slow.
We can speed this up to O(2n) complexity1 by using a simple dictionary. This adds O(2n) storage, but that hardly matters.
JavaScript
var isEqual = function (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false; // no point in wasting time if they are of different lengths
} else {
var holder = {}, i = 0, l = arr2.length;
// holder is our dictionary
arr1.forEach(function (d) {
holder[d] = true; // put each item in arr1 into the dictionary
})
for (; i < l; i++) { // run through the second array
if (!(arr2[i] in holder)) return false;
// if it's not in the dictionary, return false
}
return true; // otherwise, return true
}
}
Test Case
var arr1 = ["barry", "beth", "debbie"],
arr2 = ["beth", "barry", "debbie"];
console.log(isEqual(arr1,arr2));
// returns true
fiddle
Improvement
As Ahruss pointed out, the above function will return true for two arrays that are seemingly equal. For example, [1,1,2,3] and [1,2,2,3] would return true. To overcome this, simply use a counter in the dictionary. This works because !undefined and !0 both return true.
var isReallyEqual = function (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false; // no point in wasting time if they are of different lengths
} else {
var holder = {}, i = 0, l = arr2.length;
// holder is our dictionary
arr1.forEach(function (d) {
holder[d] = (holder[d] || 0) + 1;
// checks whether holder[d] is in the dictionary: holder[d] || 0
// this basically forces a cast to 0 if holder[d] === undefined
// then increments the value
})
for (; i < l; i++) { // run through the second array
if (!holder[arr2[i]]) { // if it's not "in" the dictionary
return false; // return false
// this works because holder[arr2[i]] can be either
// undefined or 0 (or a number > 0)
// if it's not there at all, this will correctly return false
// if it's 0 and there should be another one
// (first array has the element twice, second array has it once)
// it will also return false
} else {
holder[arr2[i]] -= 1; // otherwise decrement the counter
}
}
return true;
// all good, so return true
}
}
Test Case
var arr1 = [1, 1, 2],
arr2 = [1, 2, 2];
isEqual(arr1, arr2); // returns true
isReallyEqual(arr1, arr2); // returns false;
1: It's really O(n+m) complexity, whereby n is the size of the first array and m of the second array. However, in theory, m === n, if the arrays are equal, or the difference is nominal as n -> ∞, so it can be said to be of O(2n) complexity. If you're feeling really pedantic, you can say it's of O(n), or linear, complexity.
you can use this function to compare two arrays
function getMatch(a, b) {
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
if ( a[i] === b[e] ){
return true;
}
}
}
}
Feed your arrays to the following function:
function isArrayEqual(firstArray, secondArray) {
if (firstArray === secondArray) return true;
if (firstArray == null || secondArray == null) return false;
if (firstArray.length != secondArray.length) return false;
// optional - sort the arrays
// firstArray.sort();
// secondArray.sort();
for (var i = 0; i < firstArray.length; ++i) {
if (firstArray[i] !== secondArray[i]) return false;
}
return true;
}
Now you may be thinking, can't I just say arrayOne.sort() and arrayTwo.sort() then compare if arrayOne == arrayTwo? The answer is no you can't in your case. While their contents may be the same, they're not the same object (comparison by reference).
You need to simply sort them, then compare them
function compareArrayItems(array1, array2){
array1 = array1.sort();
array2 = array2.sort();
return array1.equals(array2);
}
fiddle
You can use the equals function provided in How to compare arrays in JavaScript?
Sort them firstly. Secondly, if their length is different, then they're not a match.
After that, iterate one array and test a[i] with b[i], a being the first array, b the second.
var search1 = ["barry", "beth", "debbie"],
search2 = ["beth", "barry", "debbie"];
// If length are different, than we have no match.
if ((search1.length != search2.length) || (search1 == null || search2 == null))
document.write("Nothing matches");
var a = search1.sort(),
b = search2.sort(),
areEqual = true;
for (var i = 0; i < a.length; i++) {
// if any two values from the two arrays are different, than we have no match.
if (a[i] != b[i]) {
areEqual = false;
break; // no need to continue
}
}
document.write(areEqual ? "We've found a match!" : "Nothing matches");
When I call this with [1,2,3,4], it returns undefined and I'm not understanding why. The goal is for it to return true if any combination of numbers in the array add up to the maximum number in the array, and false if it's not possible.
function ArrayAdditionI(arr) {
var max = Math.max.apply(null, arr);
arr.splice(arr.indexOf(max), 1);
var sum = function(arr) { return arr.reduce(function(a,b) { return a + b; }); };
function combos(arr) {
var f = function(prefix, arr) {
for (var i = 0; i < arr.length; i++) {
var clone = prefix.slice(0);
clone.push(arr[i]);
if (sum(clone) == max) { return true; }
return f(clone, arr.slice(i+1));
}
}
return f([], arr);
}
return combos(arr);
}
f is returning undefined when it is called with an empty arr! You will need to explicitly return false if none of the tests in the loop returned from the function. And you must not return false on the first occasion of the loop, but break only when you found true and continue the loop elsewhile.
To fix this, you'd have something like
function combos(arr) {
function f(prefix, arr) {
for (var i = 0; i < arr.length; i++) {
var clone = prefix.slice(0);
clone.push(arr[i]);
if (sum(clone) == max) return true;
if (f(clone, arr.slice(i+1))) return true;
}
return false;
}
return f([], arr);
}
However, also your recursion scheme with the loop looks a bit complicated. I would rather go with the naive enumeration of the "binary tree", where the nodes of each level decide whether the current item will be included in the to-be-tested subset:
function ArrayAdditionI(arr) {
var max = Math.max.apply(null, arr);
arr.splice(arr.indexOf(max), 1);
var sum = function(arr) { return arr.reduce(function(a,b) { return a + b; }, 0); };
function f(subset, arr) {
return arr.length
? f(subset, arr.slice(1)) || f(subset.concat([arr[0]]), arr.slice(1))
: sum(subset) == max
}
return f([], arr);
}
It seems that you don't test all the possible combination.
Here you will test 1+2+3, 2+3, 3 but never 1+3.
Do you really want to have a recursive function here ?
There may be some more simple way to find that.
function ArrayAdditionI(arr) {
var max = Math.max.apply(null, arr);
arr.splice(arr.indexOf(max), 1);
var res = arr.filter(function(num, idx) {
var combination = false;
// Check all combination non previously tested
for (var i = idx; i < arr.length - 1; i++) {
if (num + arr[i+1] === max) {
combination = true;
break;
}
}
return combination;
});
return res.length > 0;
}
The problem is your f function is not ever hitting the
if (sum(clone) == max) { return true; }
line of code so it will just keep recursively calling until arr.length == 0 and it will return undefined.
Your variables torf and results are unused, maybe you forgot to do something with them?
I need to test whether each item in an array is identical to each other. For example:
var list = ["l","r","b"]
Should evaluate as false, because each item is not identical. On the other hand this:
var list = ["b", "b", "b"]
Should evaluate as true because they are all identical. What would be the most efficient (in speed/resources) way of achieving this?
In ES5, you could do:
arr.every(function(v, i, a) {
// first item: nothing to compare with (and, single element arrays should return true)
// otherwise: compare current value to previous value
return i === 0 || v === a[i - 1];
});
.every does short-circuit as well.
function identical(array) {
for(var i = 0; i < array.length - 1; i++) {
if(array[i] !== array[i+1]) {
return false;
}
}
return true;
}
You could always do a new Set, and check the length.
var set1 = [...new Set(list)].length === 1;
The one line answer is:
arr.every((val, ind, arr) => val === arr[0]);
You can look into Array.every for more details.
Note:
Array.every is available ES5 onwards.
This method returns true for any condition put on an empty array.
Syntax: arr.every(callback[, thisArg]) or array.every(function(currentValue, index, arr), thisValue)
It does not change the original array
The execution of every() is short-circuited. As soon as every() finds an array element that doesn't match the predicate, it immediately returns false and doesn't iterate over the remaining elements
arr.every(i=>i==arr[0]) //will return true if all items in arr are identical
function matchList(list) {
var listItem = list[0];
for (index in list) {
if(list[index] != listItem {
return false;
}
}
return true;
}
var list = ["b", "b", "b"];
var checkItem = list[0];
var isSame = true;
for (var i = 0; i < list.length; i++) {
if (list[i] != checkItem) {
isSame = false;
break;
}
}
return isSame;
function identical(array) {
// a variable holding standard value
//against this standard value we are examining the array
var standard = array[1];
for (var i = 0; i < array.length; i++) {
if (array[i] !== standard) {
return false;
}
}
return true;
}
identical([1, 1, 1, 1, 1]); //return true
identical(['a', 'a', 'a']); //return true
identical(['a', 'a', 'b'])
function identical(array) {
// a variable holding standard value
//against this standard value we are examining the array
var standard = array[1];
for (var i = 0; i < array.length; i++) {
if (array[i] !== standard) {
return false;
}
}
return true;
}
identical([1, 1, 1, 1, 1]); //return true
identical(['a', 'a', 'a']); //return true
identical(['a', 'a', 'b'])
My suggestion would be to remove duplicates (check out Easiest way to find duplicate values in a JavaScript array), and then check to see if the length == 1. That would mean that all items were the same.
function allEqual(list)
{
if(list.length == 0 || list.length == 1)
{
return true;
}
for (index in list) {
if(list[index] != list[index+1] {
return false;
}
}
return true;
}