javascript/jQuery Array concatenation? - javascript

I have some simple jQuery code:
var response = Array()
$('.task-list').each(function() {
response.concat(response,$('#' + this.id).sortable('toArray'));
}
);
console.log(response);
The problem I'm having is that I think I'm using concat improperly- the result is an empty array. When I use array push, it works correctly.

You have to set response to the newly formed array, as described in the specification. You currently don't use the return value at all.
The specification says that for .concat, the array is not altered, but the new array is returned:
When the concat method is called with zero or more arguments item1, item2, etc., it returns an array containing the array elements of the object followed by the array elements of each argument in order.
Compare with .push, which says the current array is altered, and that something else is returned instead (the new length):
The arguments are appended to the end of the array, in the order in which they appear. The new length of the array is returned as the result of the call.
So:
response = response.concat($('#' + this.id).sortable('toArray'));

Concat returns the concatenated array, you want this instead
response = response.concat($('#' + this.id).sortable('toArray'));
Simple example
var a = [1,2];
var b = [3,4];
a = a.concat( b ); // result is [1,2,3,4] which is correct
If you do the following
a = a.concat( a , b ); // result is [1, 2, 1, 2, 3, 4] not what you want.

Related

How does join() produce different results depending on the arguments?

I can't quite understand why the join() call below produces different results, depending on the type of argument(s) provided.
Here's what I found:
var test = function() {
var args = Array.prototype.join.call(arguments,"_");
return args
};
console.log(test([1,2,3])) // #1: returns 1,2,3
console.log(test(1,2,3)) // #2: returns 1_2_3
Given join(arguments, '_'), shouldn't it produce a _ delimited string in both tests above? Why does #1 return a comma delimited value instead?
When you pass an array to test, the arguments object becomes an array of arrays, not a plain array of plain values. It's the difference between
arguments = [[1,2,3]];
and
arguments = [1,2,3];
When you call .join on an array of arrays, each inner array gets implicitly coerced to a string first, resulting in '1,2,3' - the values of the inner arrays do not get .joined by the delimiter, only the immediate children of the outer array get .joined by the delimiter.
In your code, you only have one argument in the first example, that being an array. Joining a single element will remove the brackets:
var test = function() {
var args = Array.prototype.join.call(arguments,"_");
return args
};
console.log(test([1,2,3])) // args = [[1,2,3]]
console.log(test(1,2,3)) // args = [1,2,3]
console.log([[1,2,3]].join('_'))
console.log([1,2,3].join('_'))
Another way to look at this is to provide another array as an argument to test():
var test = function() {
var args = Array.prototype.join.call(arguments,"_");
return args
};
console.log(test([1,2,3], [4,5,6]))
In the first example you are not calling .join on the array but on arguments. That variable will be populated with an array-like object that has an array as first index, in essence, you are calling the equivalent of:
let myArguments = [[1, 2, 3]];
console.log(myArguments.join("_"));
instead of what you do (the equivalent of) in the second example:
let myArguments = [1, 2, 3];
console.log(myArguments.join("_"));
The first one, first argument is [1,2,3] which is joined with the second argument, which is nothing -> output is [1,2,3].toString().
Second call, it's actually joining all the 3 arguments, resulting in outputting 1_2_3.
Because you're passing one argument which is an array - so it converts it to a string, then attempts to join it to the other arguments (there are none) so it just returns the string.
var test = function() {
var args = Array.prototype.join.call(arguments, "_");
return args
};
console.log(test([1, 2, 3]));
console.log(test(1, 2, 3));
You can solve this by checking if there's only one argument passed.
var test = function() {
var args = arguments.length == 1 ? arguments[0].join("_") : Array.prototype.join.call(arguments, "_");
return args;
};
console.log(test([1, 2, 3]));
console.log(test(1, 2, 3));
The result is different, because arguments is different.
On the first call (test([1,2,3]), you have one argument which is an array.
On the second call, you have 3 arguments, each one being a number.
Array.prototype.join is meant to be called over arrays. It will stringify each of the items in the array.
In you your first case, your arguments "array" has only one member, which is an array itself. This argument will be stringfied. An array stringfied becomes exactly what is logged in your code.

What is happening when adding a number to the array element

Example 1:
Var arr = [1,2,3] + 1;
console.log(arr) // "1,2,31"
typeof arr // String
Example 2:
var arr = 5 + ["h","e","l","l","o"];
console.log(arr) // "5h,e,l,l,o";
typeof arr // String
Doing the above concatenate the number/string to the last/first element in the array. Would like to understand what happens here?
While you are using + (concatenation in this case ), it's applying toString() method to the array. So it's just concatenating with the result and not appending with last or first element.
The Array object overrides the toString method of Object. For Array objects, the toString method joins the array and returns one string containing each array element separated by commas.
JavaScript calls the toString method automatically when an array is to be represented as a text value or when an array is referred to in a string concatenation. (Taken from here)
Check the following snippet all those are results the same.
var arr = [1, 2, 3];
// all these are providing the same result
// result of toString method
console.log(arr.toString())
// concatenation with empty string at end
console.log(arr + "")
// concatenation with empty string at start
console.log("" + arr);
To add an element to the array use one of this methods.
As #Pranav C Balan mentioned + operator try to concatenate 2 values. That's one of the most weird parts in Javascript. Here is a very helpful page with all of subtleties JS Garden
Example 1:
Var arr = [1,2,3];
arr.push(1)
console.log(arr) // [1,2,3,1]
typeof arr // object
Example 2:
var arr = ["h","e","l","l","o"];
arr.unshift(5);
console.log(arr) // [5,"h","e","l","l","o"];
typeof arr // object

.map not working as expected on uninitiated array

Using .map() on an array full of undefined values (eg new Array(10)) will always return an array of the same length with undefined values, no matter what you return.
new Array(10).map(function(){return 5;});
will return a new array filled with 10x undefined. Why does this happen?
Because when you define an array like that, the spaces for values are empty slots and are not iterated over by map() or any of its friends.
There is Array.prototype.fill() (in ES6) which can be used to set values on that array.
You could use
var array = Array.apply(null, { length: 10 }).map(function(){ return 5; });
var array = Array.apply(null, { length: 10 }).map(function() { return 5; });
document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');
from the fine manual:
map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values, including undefined. It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).
new Array(10)
creates missing elements, if that makes any sense.
Like this one:
var b=new Array();
b[30] = 1;
var c = b.map(function(){return 5;});
> [undefined × 30, 5]
There's an answer for this here: https://stackoverflow.com/a/5501711/6206601. Look at the top comment for further clarification.

Empty elements in JS array declaration

it's my first question here, after have been reading for years, so be nice with me please.
I'm having trouble with array management in js/jq.
I have array with several elements, which is processed with $.each function.
I want to extract matching elements to another array and return this array.
But for some reason (don't know if it's because array declaration, jquery.each function...) I'm having first empty element.
I think I'm making this more difficult to understand than it's, so made jsfiddle.
var arr = new Array();
$.each([1,2,3], function(index,element){
if (element == 2){
arr[index] = element;
}
});
arr must have only 1 element, but arr.length returns 2 because first array slot is empty.
Here is a fiddle http://jsfiddle.net/moay7y95/
I'm so sure that it's a simple and little stupid thing, but I've not been able to find an answer.
Thanks in advance!
You are pushing an element in array at 1st index. So, javascript by default put undefined at 0th index.
So, at the end of each your array will be
[undefined, 2];
This is the reason you get the length as 2.
You can use push to add element in array:
$.each([1, 2, 3], function (index, element) {
if (element == 2) {
arr.push(element);
elem++;
}
});
Demo: https://jsfiddle.net/tusharj/moay7y95/2/
The push() method adds one or more elements to the end of an array and returns the new length of the array.
Docs: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/push
Best solution: Use .filter
var arr = [1, 2, 3].filter(function(value){
return value == 2
});
If the return value is true, the element is included in the returned array, otherwise it is ignored. This is pure js, so you don't need jquery. See documentation about .filter
Your problem: Use .push
Try using the .push method on the array (see Mozilla's documentation).
var arr = new Array();
$.each([1,2,3], function(index,element){
if (element == 2){
arr.push(element);
}
});
The .push method will dynamically grow your array as elements are added.
Your problem is that the value of index inside your function is a reference point in your initial array. This means that if you look at the returned array, you will find [undefined, 2] and so the length is returning as 2. If your condition were element == 3 you would have two empty slots.
Alternatively: Use .grep
Another jQuery method is $.grep. See http://api.jquery.com/jquery.grep/
var arr = $.grep([1, 2, 3], function (value) {
return value == 2
});
This is jQuery's implementation of javascript's .filter.
Your array [1, 2, 3] has three elements, and three associated indexes: 0, 1 and 2. In each iteration of your $.each() loop over that array, the index and its value get passed to the function.
So the first call gets 0, 1 passed as its arguments. The second call gets 1, 2 passed as its arguments, then the if statement condition evaluates to true, so your code:
arr[index] = element;
is actually equivalent to
arr[1] = 2;
Since you're inserting an element at index 1, you'll end up with an empty index 0.
You could instead simply use Array.push() to add the element to the array:
arr.push(element);
As already mentioned the problem is you are assigning the value at index 1, so the array will be considered of length 2.
One solution is to use .push() instead of assigning based on index.
Another approach could be is to use Array.filter() and return true if the element matches the conditon
var arr = [1, 2, 3].filter(function(value){
return value == 2
});
Demo: Fiddle
Using $.grep()
var arr = $.grep([1, 2, 3], function (value) {
return value == 2
});
[1, 2, 3]
if (element == 2)
arr[index] = element;
This means you're setting arr[1] to element.
If you want to add it to the arr sequentially (filling it up normally), push it into art
arr.push(element);
Seems like you're looking for Array.filter (MDN).
var elems = ["car", "bike"];
var arr = [1, 2, 3, "car", 5, "bike"].filter(myFilterFunc);
function myFilterFunc(val) {
if (elems.indexOf(val) > -1) return true;
}
Fiddle

How to get value at a specific index of array In JavaScript?

I have an array and simply want to get the element at index 1.
var myValues = new Array();
var valueAtIndex1 = myValues.getValue(1); // (something like this)
How can I get the value at the 1st index of my array in JavaScript?
You can access an element at a specific index using the bracket notation accessor.
var valueAtIndex1 = myValues[1];
On newer browsers/JavaScript engines (see browser compatibility here), you can also use the .at() method on arrays.
var valueAtIndex1 = myValues.at(1);
On positive indexes, both methods work the same (the first one being more common). Array.prototype.at() however allows you to access elements starting from the end of the array by passing a negative number. Passing -1 will give the last element of the array, passing -2 the second last, etc.
See more details at the MDN documentation.
Array indexes in JavaScript start at zero for the first item, so try this:
var firstArrayItem = myValues[0]
Of course, if you actually want the second item in the array at index 1, then it's myValues[1].
See Accessing array elements for more info.
You can just use []:
var valueAtIndex1 = myValues[1];
indexer (array[index]) is the most frequent use. An alternative is at array method:
const cart = ['apple', 'banana', 'pear'];
cart.at(0) // 'apple'
cart.at(2) // 'pear'
If you come from another programming language, maybe it looks more familiar.
shift can be used in places where you want to get the first element (index=0) of an array and chain with other array methods.
example:
const comps = [{}, {}, {}]
const specComp = comps
.map(fn1)
.filter(fn2)
.shift()
Remember shift mutates the array, which is very different from accessing via an indexer.
Update 2022
With ES2022 you can use Array.prototype.at():
const myValues = [1, 2, 3]
myValues.at(1) // 2
at() also supports negative index, which returns an element from the end of the array:
const myValues = [1, 2, 3]
myValues.at(-1) // 3
myValues.at(-2) // 2
Read more:
MDN, JavascriptTutorial, Specifications
You can use [];
var indexValue = Index[1];
As you specifically want to get the element at index 1. You can also achieve this by using Array destructuring from ES6.
const arr = [1, 2, 3, 4];
const [zeroIndex, firstIndex, ...remaining] = arr;
console.log(firstIndex); // 2
Or, As per ES2022. You can also use Array.at()
const arr = [1, 2, 3, 4];
console.log(arr.at(1)); // 2

Categories

Resources