Javascript pushing Array to Array but concatenating instead - javascript

I'm trying to push an array (multiple times) into another array. Instead of an array of arrays, I'm getting all the values from the multiple push attempts as a single array. I've tried pushing an array implicitly (i.e. push([val1,val2]), explicitly creating a new Array, then pushing the new Array. Here's the key part of the code:
var coordinates=[];
...
for(i=0;i<6;i++)
{
...
for(var j=start;j<circum[i].length;j++)
{
var segmentCoords=[];
...
if(segmentFlag===false)
{
segmentCoords.push([i+1,segmentLength]);
segmentFlag=true;
}
...
if(segmentFlag===true)
{
var tempArray=new Array(i+1,segmentLength);
segmentCoords.push(tempArray);
segmentLength+=sectorLength;
coordinates.push(segmentCoords);
segmentFlag===false;
}
...
}
From the many stackoverflow questions/answers I've looked at, I expect my coordinates array to look something like this: [[val1, val2],[val3,val4],[val5,val6]]. Instead it's [val1,val2,val3,val4,val5,val6]. That is what I would expect if I were using .concat() or .apply().
Can anyone explain why my code isn't generating an array of arrays?
I've got the full code here https://jsfiddle.net/Seytom/7xm9s4qr/ in case you want to see more of it.

You seem to be fooled by your console.log. Notice the difference between these two statements:
console.log( 'string ' + [[1,2],[3,4]] ); // string, '1,2,3,4'
console.log( 'string ', [[1,2],[3,4]] ); // string, [[1,2],[3,4]]
Because you are coercing the array into a string, this is the result. Its the same as:
console.log( new Array([1,2],[3,4]).join(',') ); // 1,2,3,4
It's simply what arrays do when you join them, regardless of whether they are nested. It is better to log the array separately so you can explore it in your console, so simple print your string and then add the array as the second argument. (The console takes an infinite amount of arguments and will print them all as one statement - safari even prints the first as a special type if its a string so its clearer to read).
In short: push behaves exactly as expected, and your code should simply work as intended, but the printing to the console seems to leave a bit to be desired :).

Use Array.concat:
var arrA = [0];
var arrB = [1, 2];
while (arrA.length < 10) {
arrA = arrA.concat(arrB)
}
console.log(arrA)

Related

Multiple arrays inside a array in javascript

when i do console.log(myArray) I obtain this:
console.log result
I want to take a value inside only one of this arrays, but how? When i do console.log(array[0]) I obtain this result:
37.7
28.45
36.38
You have nested arrays. So your main array has three elements each of which contains one number, and the indexes of those arrays go from 0 to 2.
You access each nested array with its index, and then access the number with the 0 index (because there's only one element in that nested array).
const arr = [[37.7], [28.45], [36.38]];
console.log(arr[0][0]);
console.log(arr[1][0]);
console.log(arr[2][0]);
Or even loop over the array and destructure the number from each nested array:
const arr = [[37.7], [28.45], [36.38]];
for (let [number] of arr) {
console.log(number);
}
From what I can see in the original question so far, the output of this function is actually three different console.log() executions, which leads me to believe that whatever is firing these console.logs is actually running in some sort of loop.
If that is the case, you will not be able to pull just one value out to simply. The screenshot you added only shows the output. Could you please add the code for (or screenshot of) all the related code from setting up or fetching the array, to your console.log? With all that context, I can rewrite my answer to get you the exact answer you are looking for.
Please compare your code with this working example:
let myArray = [37.7, 28.45, 36.38];
console.log(myArray[0]); // outputs 37.7

Forcing string representation of an array key

I am trying to maintain the order of an array with mixed key types. The array contains mostly keys represented by string values -- but if you enter a numbered key it goes to the front. How can I force a key which is a number to be a string type?
E.g.
array = [];
array["one"] = "some data";
array["two"] = "some more data";
array["3"] = "this should not be the first element";
How can I make "3" a string type to prevent it from moving to the top of the index?
Oh wow did you ever open multiple cans of worms.
Javascript arrays are a special type of Javascript objects, and like all Javascript objects they can have arbitrary string properties:
const foo = [];
foo["bar"] = "hi";
However that string is a property of the array object, not an item in the array:
foo.forEach(console.log); // logs nothing
You can still access it like any other object property:
console.log(foo["bar"]); // "hi"
But it won't show up in the usual iterative constructs like c-style for loops or the map/forEach array methods.
The line in your example
array["3"] = "this should not be the first element";
is very different however, because of Javascript's playing fast and loose with type conversions this actually sets the string to the 4th slot in the array:
const bar = [];
bar["3"] = "oops!"; // equivalent to bar[3] = "oops!"
console.log(bar); // [empty x 3, "oops!"]
This piece of it is actually a good thing (other than the implicit conversion part) rather than a problem: sometimes you need a sparse array and JS supports those. Iterating it will only produce the one element:
bar.forEach((item, index) => console.log(item, index)); // ["oops", 3]
Note though that the string has the correct index of 3, and can be accessed that way even though there's nothing "in front" of it:
bar[3]; // "oops"
So the first two assignments in your example create properties on the array object, and the third assignment is the only one that actually adds an item to the array, at the 4th index (there's nothing at the first 3).
What you seem to want as Reese Casey suggests, is a plain object:
const foo = {}; // curly
foo["some string"] = "whatever";
However now the properties are basically unordered. If you want them to be in a guaranteed specific order you do want an array, but all your indicies will need to be integers, and should be sequential. You can achieve this easily by using the .push method:
foo = [];
foo.push("something");
foo.push("something else");
Now foo will have two elements, in the correct order, and index 0 and 1 respectively.
Update based on comment on the other answer:
I want some of the data to be ordered, and the rest of the data to follow
This can be accomplished through object destructuring:
const responseFromDB = {
oneKeyICareAbout: 3,
anotherKeyICareAbout: 2,
foo: 6,
bar: 7,
};
const {
oneKeyICareAbout,
anotherKeyICareAbout,
*rest,
} = responseFromDB;
const stuffToDisplay = [
oneKeyICareAbout,
anotherKeyICareAbout,
...Object.values(rest),
]; // [3, 2, 6, 7]
And at least the destructured stuff you put in the array will be ordered because by doing so you've ordered it.
Javascript arrays cannot have string indexes. This is actually working incorrectly as the index is adding a property to the array object.
Changing to an object makes more sense for this.
EDIT: Whilst below its mentioned you can have string indexes you are not actually using the array by doing so. The answer by Jared Smith goes into much more detail as to why.
The other answers explain what is happening with your array-object mixture. For having an indexable thing which can reproduce the original order, you can use a Map:
The Map object holds key-value pairs and remembers the original insertion order of the keys.
array = new Map();
array.set("one","some data");
array.set("two","some more data");
array.set("3","this should not be the first element");
console.log("Test of get:",array.get("two"));
console.log("Test of order:");
for(let entry of array)
console.log(entry);

Reversing an array which is a value in object in Javascript

I am trying to reverse an array which is an element in an object.
colorKey = {
"2m":["#ffffff","#000000"]
}
colorKey["2mi"] = colorKey["2m"];
Array.reverse(colorKey["2mi"])
This is not working and returning colorKey["2mi"] the same as colorKey["2m"]. When I run the same command in developer console in browser, it reverses successfully. Where is the problem?
This is no static method off Array called reverse. reverse is an instance method (Array.prototype.reverse) off the Array object, so the instance of the Array must be the caller.
This solves your problem:
colorKey = {
"2m":["#ffffff","#000000"]
}
colorKey["2mi"] = colorKey["2m"];
colorKey["2mi"].reverse();
Output:
["#000000", "#ffffff"]
Calling reverse() for an array mutates it (reverse is in place - a new array is not created). What you want, apparently, is to have a reversed copy of the array. Basically, create a new array with the same values and then reverse it.
var a = [1, 2], b;
b = a.slice(0).reverse();
Slice creates a new array with the same elements (but remember that it is not cloning the elements).
#Rajat Aggarwal
What you are asking for, is to clone your previous array in reverse order.
The only trivial part of it would be reversing it. Because there is no way of cloning Objects and Arrays, nor a general method that you could write down as a function to be using it universally.
This specific array from the sample you provided can be cloned easily because it is flat and it only contains primitives. But the solution to it, will be exactly as specific as the sample array provided.
A specific solution to this task would be to use a plain coma-separated string of successive values and convert that to specific arrays of their corresponding primitive values.:
var colors = "#ffffff,#000000";
var colorKey = {
"2m":colors.split(","),
"2mi":colors.split(",").reverse()
}
which will yield you a:
>> colorKey
{
2m : #ffffff,#000000,
2mi : #000000,#ffffff
}

jQuery splice inArray with multiple key objects

Javascript newbie here --
I have the following array:
var group = ({
one: value1,
two: value2,
three: value3
});
I want to check if array "group" is part of "groupsArray" and add it if doesn't or remove it if it does.
var groupLocate = $.inArray(group, groupsArray);
if(groupLocate ==-1){
groupsArray.push(group);
} else {
groupsArray.splice($.inArray(group, groupsArray),1);
}
This method works with single value arrays. Unfortunately, I can't get it to work in this case with three keys and values as groupLocate always returns -1.
What am I doing wrong?
Thanks.
First it helps to understand why $.inArray() didn't work. Let's try a simpler case. Paste this in to the JavaScript console in your browser on a page with jQuery loaded (such as this page we're on) and run it:
var object = { a: 1 };
var array = [ { a: 1 } ];
console.log( '$.inArray: ', $.inArray( object, array ) );
(Note the terminology: your group variable is an Object, not an Array.)
Now it looks like object is in the array, right? Why does it print -1 then? Try this:
console.log( object );
console.log( array[0] );
They look the same. How about:
console.log( '== or === works? ', object == array[0], object === array[0] );
Or even simpler:
console.log( 'Does {a:1} == {a:1}? ', {a:1} == {a:1} );
console.log( 'What about {} == {}? ', {} == {} );
Those all print false!
This is because two objects that happen to have the same content are still two separate objects, and when you use == or === to compare two objects, you are actually testing whether they are both references to one and the same object. Two different objects will never compare equal, even if they contain exactly the same content.
$.inArray() works like using an === operator to compare two objects - it won't find an object in an array unless it is the same object, not just an object with identical content.
Knowing this, does that suggest any possible ways to approach the problem? There are several ways you could write your own code to search the array for your object, or you may find it helpful to use a library such as Underscore.js which has many useful methods for arrays and objects.
For example, you could use _.findWhere( groupsArray, group ) to find the first match - with the caveat that it only compares the properties that are in the group object. For example, if group is {a:1}, it would match an object in the groupsArray array that was {a:1,b:2}.
If you need an exact match, you could combine Underscore's _.find() and _.isEqual() methods:
var index = _.find( groupsArray, function( element ) {
return _.isEqual( element, group );
});
Now one last thing to watch out for. Your code that pushes the group object onto the groupsArray array - you know that pushes the actual group object itself. It doesn't make a copy of it in the array, it's a reference to the very same object. (Ironically, this means that your original code to find group in the array would actually work in the case where you'd pushed that same group object onto the array yourself.)
If you want to make sure the elements in groupsArray are each their own independent object, and not a reference to another object floating around in your code, you can use another Underscore method to do a shallow copy:
groupsArray.push( _.clone(group) );
If group has any nested objects, though, this won't copy them. (I don't see a deep copy function in Underscore, although you could write one if you need it.)

JavaScript array's length method

Can anyone explain why the second alert says 0 ?
var pollData = new Array();
pollData['pollType'] = 2;
alert(pollData['pollType']); // This prints 2
alert(pollData.length); // This prints 0 ??
The length of the array is only changed when you add numeric indexes. For example,
pollData["randomString"] = 23;
has no effect on length, but
var pollData = [];
pollData["45"] = "Hello";
pollData.length; // 46
changes the length to 46. Note that it doesn't matter if the key was a number or a string, as long as it is a numeric integer.
Besides, you are not supposed to use arrays in this manner. Consider it more of a side effect, since arrays are objects too, and in JavaScript any object can hold arbitrary keys as strings.
Because you haven't put anything into the array yet. You've only been assigning to a dynamically-created pollType attribute on the array object.
If you use numeric indices, then the array automagically takes care of length. For example:
var arr = [ ]; // same as new Array()
arr[2] = 'Banana!';
alert(arr.length); // prints 3 (indexes 0 through 2 were created)
The length property takes into consideration only those members of the array which names are indexes (like '1', '2', '3', ... ).
Arrays in JavaScript have numeric indexes only.
Use an object, which is essentially what you are doing above, setting properties on that array object.
array.length returns how many values are stored in the array. The first alert is returning the value of the position 'pollType'.
The reference guide I always use when needing help with javascript arrays is this page http://www.hunlock.com/blogs/Mastering_Javascript_Arrays
I'd also read what it says under the heading Javascript Does Not Support Associative Arrays, as you may run into problems with this also.
var pollData = Array();
function test() {
pollData[0] = 2
alert(pollData[0]);
alert(pollData.length);
}
//[x] is the array position; hence ['polltype'] is causing issues

Categories

Resources