So if I had:
A=['a','b','c'];
B=[];
for (var i = 0;i<7;i++){
B.push(A[i])
}
I would get
B=["a", "b", "c", undefined, undefined, undefined, undefined]
Instead I want
B= ["a","b","c"]
So I guess I would need something like
for (var i = 0;i<7;i++){
B.push(A[i] "unless A[i] is undefined. Then don't push anything")
}
How would I do this in Javascript?
Some ES magic
[1, 2, undefined].filter(Boolean)
will produce
[1, 2]
I think this is what you're searching:
Array#filter
B = A.filter(function (element) {
return element !== undefined;
});
That Code will make a duplicate of A filtering out all undefined elements.
Instead of iterating the array and pushing elements one at a time to a new array, it's usually more efficient to use the Array.filter function, like so:
var B = A.filter(function(item){ return item !== undefined; });
You may also want to be cautious about using undefined. This is easily confused with other constructs such as null or empty strings. If you use "!=" instead of "!==" in the function, that will filter out null or missing array items, as well as items which are set specifically as undefined.
You could add a safeguard like
A[i] && B.push(A[i])
which would only push if A1 returns a true, but that would also give false if A[i] would be 0
Example
I would suggest checking against null
if (A[i] != null) B.push(A[i])
Example
If you want to keep your first forloop as it is you can "clean" the array after by using filter. Like:
for (var i = 0; i < 7; i++) {
B.push(A[i])
}
var clean_B = B.filter(function (item) {
return item != null;
});
Example
An Object Oriented Aspect
=> After that code, clean your array :
B.clean();
Known that clean is an extension of array Class(OOP context)
Array.prototype.clean=function(){
var newArray = [];
for(var index = 0; index < this.length; index++) {
if(this[index]) {
newArray.push(this[index]);
}
}
return newArray;
};
You stated the answer to your question in your sort-of comment (use // at the end of the line next time, no need for inserting a comment in a string).
unless A[i] is undefined. Then don't push anything
Another way of putting it is, if A[i] is not undefined, then push.
When put like that, it directly translates into code.
if (A[i] !== undefined)
{
B.push(A[i]);
}
I elaborated on your comment to show you how easily you can figure these types of questions out with a little effort and time.
However, as others have stated, a much better way of ignoring undefined indices is to simply iterate to A.length, however this only works if there are no undefined values in-between the defined values (which is still likely the case).
Your problem would be solved by iterating from 1 to array.length, or by using a for in loop
If you're going to be dealing with arrays that could have undefined elements, for example [0, undefined, 4], then you'd need to check if the element is defined before you add it. if(a[i] !== undefined) will do the trick.
You would use an if statement
for (var i = 0; i < 7; i++){
if (A[i] !== undefined) {
B.push(A[i]);
}
}
You can have a compact function to filter out undefined values:
function compact(col) {
return col.filter(function(val) {
return val !== undefined;
});
}
console.log(compact([false,0,1,null,undefined])); // [false,0,1,null]
JS Bin Example
http://jsbin.com/mabowana/4/edit
initials:
A = ['a', 'b', 'c'];
B = [];
I think, the closest answer to OP's question would be this:
for (var i = 0; i < 7; i++) {
if (typeof A[i] !== "undefined") B.push(A[i]);
else continue;
}
or this one:
for (elem of A) if (typeof elem !== "undefined") B.push(elem); else continue;
Instead of hard coding i < 7, use i < A.length
for (var i = 0; i < A.length; i++){
B.push(A[i])
}
Related
This is a very simple question but I am not been able to wrap my head around it.
I have an array of pages with n number of page names, I want to run a loop with some page names not included in it.
var arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
for (var page in arr) {
if (arr[page] !== "page-name" || arr[page] !== "some-more") {
console.log(arr[page])
}
}
Now the result that I want is this:
page-name-two
page-3
another-page
What am I doing wrong?
Just take logical AND && instead of logical OR ||.
Please use a for loop with a variable for the index instead of the keys of an object.
Source:
Why is using “for…in” with array iteration a bad idea?
var arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
for (var i = 0; i < arr.length; i++) {
if (arr[i] !== "page-name" && arr[i] !== "some-more") {
console.log(arr[i]);
}
}
The expression
arr[i] !== "page-name" || arr[i] !== "some-more"
is always true, because for exampe if
arr[i] === "page-name"
then the other part is true, because of
"page-name" !== "some-more"`.
You should use .filter() to filter values from first array and then perform whatever action you want to perform on resultant array. This will save your from writing a lot of OR / AND conditions in case you need to filter more values.
let arr1 = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'],
arr2 = ["page-name", 'some-more'];
let result = arr1.filter(s => !arr2.includes(s));
console.log(result);
I would store the values that you're looking to eliminate, then run Array.filter on your list of all page names to find matches. If a name matches, remove it from the final array.
// This can be a array of whatever strings you're looking to eliminate from the array
const valuesToFilter = ['page-name', 'some-more'];
// Your original array
const arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
// Use Array.filter to eliminate anything that doesn't pass the filter test
const filteredArr = arr.filter(page => {
let foundMatch = false;
valuesToFilter.forEach(value => {
if (page === value) {
foundMatch = true;
}
})
if (!foundMatch) return page;
});
console.log(filteredArr);
Here is a simple example of an array that contains at least one other array. I want a way to find the index of an array, within an array. However, the code I have below does not work:
var arr = [1,2,[1,2]];
console.log(arr.indexOf([1,2])); //-> -1
for (var i = 0; i < arr.length; i++) {
if (arr[i] == [1,2])
return 'true' // does not return true
}
Intuitively, this should work but does not:
if ([1,2] == [1,2]) return 'true' // does not return true
Can someone explain why it does not work, and offer an alternative solution? Thanks!
No, but you can check it yourself:
var a = [1,2], b = [1,2];
a.length === b.length && a.every(function(x,y) { return x === b[y]; });
Arrays in JavaScript are compared by reference not by value. That is why
console.log([1,2] == [1,2])
returns false.
You need a custom function that could compare arrays. If you want to check only the first level of nesting you can use this code:
var compareArrays = function(a, b) {
if (a.length !== b.length) {
return false;
}
for (var i = 0, len = a.length; i < len; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
You are confusing the definitions of similar objects vs. the same object. Array.prototype.indexOf() compares the objects using the strict equality comparison algorithm. For (many) objects, this means an object reference comparison (i.e. the object's unique identifier, almost like its memory address).
In your example above, you are trying to treat two similar arrays as though they were the same array, and that's why it doesn't work. To do what you are trying to do, you need to use the same array. Like this:
var testArr = [1,2]; //a specific object with a specific reference
var arr = [1,2,testArr]; //the same array, not a different but similar array
console.log(arr.indexOf(testArr)); //returns 2
If you just want to know where arrays occur in the parent array, use Array.isArray():
...
if(Array.isArray(arr[i])) {
//do something
}
...
Hopefully that helps!
Sorry if this is a dupplicate, can't seem to find it.
var a = [1,2,3,4];
a.forEach(function(value){
if(value == 1) a.push(5);
console.log(value);
});
I wonder if there is a way (any sort of loop or datatype) so that this will ouput 1 2 3 4 5 during the loop (or in any order, as long as all the 5 numbers are in there)
Using Array.prototype.forEach() will not apply the callback to elements that are appended to, or removed from, the array during execution. From the specification:
The range of elements processed by forEach is set before the first
call to callbackfn. Elements which are appended to the array after the
call to forEach begins will not be visited by callbackfn.
You can, however, use a standard for loop with the conditional checking the current length of the array during each iteration:
for (var i = 0; i < a.length; i++) {
if (a[i] == 1) a.push(5);
console.log(a[i]);
}
Obvious solution :
var a = [1,2,3,4];
for (var i=0; i<a.length; i++){
var value = a[i];
if(value == 1) a.push(5);
console.log(value);
}
Since you appear to use Harmony, how about a generator like this:
function *iter(array) {
for (var n = 0; n < array.length; n++)
yield array[n];
}
and then
var a = [1,2,3,4];
for(var p of iter(a)) {
if(p == 1) a.push(5)
console.log(p)
}
prints 1 2 3 4 5
If you need a method that uses a callback as apposed to the for loop reduce will work.
var a = [1,2,3,4];
var result = a.reduce(function(total, item) {
total.push(item);
if (item === 4) total.push(5);
return total;
}, []);
console.log(result);
Better Alternate solution:
if (a.indexOf(1) >= 0) a.push(5);
a.forEach( ... );
OK, maybe not strictly better, since it traverses the array twice. However you ought to consider why you're trying to modify the array whilst iterating over it in the first place. It's an unusual situation.
SO this is a quick test that seems to work well :
var a = [1,2,3,4,5];
a.forEach (function (val,index,array) {
if (val == 5) {
array.push (6);
};
console.log (val);
});
a.forEach(function fn(item, index) {
if (item == 5) {
array.push (6);
};
})
var a = [1,2,3,4];
Object.keys(a).forEach(idx => {
if(a[idx]==1) a.push(5);
console.log(a[idx]);
});
OP here. I've since learned that ES6 Sets do include items added during forEach.
So if you can use a set instead of an array, you can do:
var a = new Set([1,2,3,4]);
a.forEach(function(value){
if(value == 1) a.add(5);
console.log(value);
});
which does indeed log 5 as well.
Just an alternative to the for loop. Of course Sets are different than arrays in several ways, so you'd need to understand the differences and how it effects your other code.
Simple question, but i dont know how to solve it
I have several arrays, but i only want the values that all arrays have in common
Im using javascript.
Try looking for the value in each of the arrays using indexOF.
I never knew IE didn't support indexOf, but here's a quick fix from this post.
Something like this should work:
function getCommonElements() {
var common = [],
i, j;
if (arguments.length === 0)
return common;
outerLoop:
for (i = 0; i < arguments[0].length; i++) {
for (j = 1; j < arguments.length; j++)
if (-1 === arguments[j].indexOf(arguments[0][i]))
continue outerLoop;
common.push(arguments[0][i]);
}
return common;
}
Call it with any number of arrays as arguments:
var commonEls = getCommonElements(arr1, arr2, arr3, etc);
In case it's not obvious, the idea is to loop through the array from the first argument and test each of its elements against the other arrays. As soon as a particular element is found to not be in any of the other arrays from the other arguments continue on with the next element. Otherwise add the current element to the output array, common.
If you need to support browsers (IE < 9) that don't support the Array.indexOf() method you can either include the shim shown at the MDN page or replace the .indexOf() test from my code with another loop.
I think this should work.
var arr1 = [1,2,3,4]
, arr2 = [2,3,4,5]
, arr3 = [3,4,5,6]
, arrs = [arr1, arr2, arr3];
var all = arr1.concat(arr2.concat(arr3)).sort()
, red1 = all.filter(
function(val, i, arr) {
return i === arr.lastIndexOf(val)-1;
})
, red2 = red1.filter(
function(val, i, arr) {
var shared = true;
arrs.forEach(
function(arr, i, src) {
if (arr.indexOf(val) === -1)
shared = false;
})
return shared;
})
If you are only concerned with modern browsers that support reduce(), then use this solution:
Finding matches between multiple JavaScript Arrays
If you must support IE6, then use my solution below. Here's how I got this to work in IE6 using jQuery:
// Find common values across all arrays in 'a',
// where 'a' is an array of arrays [[arr1], [arr2], ...]
Object.common = function(a) {
var aCommon = [];
for (var i=0,imax=a[0].length,nMatch,sVal; i<imax; i++) {
nMatch = 0;
sVal = a[0][i];
for (var j=1,jmax=a.length; j<jmax; j++) {
nMatch += ($.inArray(sVal, a[j])>-1) ? 1 : 0;
}
if (nMatch===a.length-1) aCommon.push(sVal);
}
return aCommon;
}
Basically, you just loop through each value of the first array in 'a' to see if it exists in the other arrays. If it exists, you increment nMatch, and after scanning the other arrays you add the value to the aCommon array if nMatch equals the total number of the other arrays.
Using the sample data provided by Florian Salihovic, Object.common(arrs) would return [3, 4].
If you cannot use jQuery, then replace $.inArray() with the code provided by Mozilla:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/IndexOf
I have a little piece of code where an array is populated with arrays. At the end, I have this array with n member arrays. These sub-arrays always have the same number of members (2) of the same type (number). I need to know if these sub-arrays are all identical (same members, same position). This always returns false:
[2, 0] === [2, 0]
Off the top of my head, I can think of two ways to compare.
A loop in which I test (member[i][0] === member[i+1][0] && member[i][1] === member[i+1][1]).
The same loop, with this test: (member[i].toString() === member[i + 1].toString()).
I think I'm taking this the wrong way. What do you think?
FOR MY OWN THINKING, I think it is correct to use the loop to compare two array.
var isTheSame = true;
for (var i in array1) {
if (array1[i] !== array2[i]) isTheSame = false;
}
The loop above works, it will return false either any of the element different from type (three equal sign ===), or value, or length or even key.
The second suggestion of you should not work as exactly as the first one, because you convert it into a string already, what happen if array1[0] = "true" and array2[0] = true? It will return true, because now all of them are string, but you need the exact comparison right?
That's my own thinking, I hope it might help somehow.
Regards,
[x]
a=[2,0]; b=[2,0]; a.toString() == b.toString();
perhaps not the most efficient, but it seems to work, and I'm a strong proponent of the shorter and more readable solution.
note that xx3004's point about the type data lost when converting to string is something to think about, unless you know for sure that your arrays will be composed of the same data types.
You can use the below to get true or false on whether two one-dimensional arrays are identical. It needs to be recursive if you add dimensions, but this will suffice for what you're asking, I think.
function testArray(a, b) {
var aLen = a.length;
var bLen = b.length;
if (aLen === bLen) { // check for identical length first
for (var i = 0; i < aLen; i++) {
if (a[i] !== b[i]) {
return false; // members don't match
}
}
return true; // all members matched
}
return false; // not same length
}
http://jsfiddle.net/pgkUr/
This is what I came up with...
var arrayCompare = function(a, b) {
var aLength = a.length,
bLength = b.length;
if (aLength != bLength) {
return false;
}
for (var i = 0; i < aLength; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
Here's an easy way to compare the two arrays, building on your toString idea (even multidimensional ones will work):
function compareArrays(a1, a2) {
return JSON.stringify(a1) == JSON.stringify(a2);
}
compareArrays([[2,3],[7,4],[3,3]], [[2,3],[7,4],[3,3]]) // true
compareArrays([[2,3],[7,4],[3,3]], [[7,4],[2,3],[3,3]]) // false
If your willing to use Underscore, which is simply great tool (I value it as much or even higher than jQuery), you could simplify this code quite a lot. You don't need nesting during comparing arrays: I would flatten them beforehand. Then it's just one loop:
function cmpArrays( arr1, arr2 ){
var flat = _.zip( _.flatten( arr1 ), _.flatten( arr2 ) );
for( var elem in flat ){
if( flat[elem][0] !== flat[elem][1] ){
return false;
}
}
return true;
}
generalizing this to work with any number of arrays should be very simple as well.