Javascript table multidimension - javascript

Hello i'm begignner at javascript, I wrote the code below and get this error in my console "SyntaxError: Unexpected token ,"
var tab1=[{0,2,4,6,8},{1,3,5,7}];
console.log(tab1[0][0]);

Please change the curly to square brackets:
var tab1 = [[0, 2, 4, 6, 8], [1, 3, 5, 7]];
[] are used for arrays, {} are used for objects.
Examples:
array = ['a', 'b', 'c'];
object = { property: 'one', key: 'two' };

{} is for creating objects; it expects key: value pairs inside, which are called property initializers.
[] is for creating arrays.
So if you want to create an array of arrays (JavaScript doesn't have two-dimensional arrays, but arrays of arrays work just as well), use nested []:
var tab1=[[0,2,4,6,8],[1,3,5,7]];
Just for completeness, here's an example of an object rather than array:
var obj = {
question: "Life, the Universe, and Everything",
answer: 42
};
The reason for the error is that you just had 0,2 and it was expecting a : after the 0. (Literal numbers are valid object keys, which is why the 0 wasn't the problem.)

Related

Why object merges properties but array does not merges values

Can someone tell why object merges values but array does not
See the code block below:
const a = {'a': 1, 'b': 2}
const b = {'b': 4, 'c': 3}
console.log({...a, ...b})
This Outputs
{ a: 1, b: 4, c: 3 }
But when I use the code below:
const c = [1,2]
const d = [2,3]
console.log([...c, ...d])
This outputs
[ 1, 2, 2, 3 ]
Why object merges properties...
It doesn't merge properties, it merges objects. Notice the value of b in your result: It's 4 (the value from the b object), not some merged value of 2 (from the a object) and 4 (from the b object). Each property from each source object is just copied into the target object (with later objects overwriting properties from earlier objects), the properties themselves are not merged together.
But fundamentally, object property spread and iterable spread are just completely different things with different purposes and different semantics, because objects and arrays are different beasts (at least conceptually; arrays actually are objects in JavaScript). Properties have names which are an intrinsic part of the property. Array elements just have indexes, and it's normal for values to be moved around an array (moved to different indexes). The two different definitions of spread are each useful for the data type they're defined for.
If you want to treat an array like an object, though, you can since arrays are objects in JavaScript. (Although in this case it isn't useful.) Here's an example (I've changed c's element values so it's clear what's coming from where):
const c = ["a", "b"];
const d = [2, 3];
console.log(Object.assign([], c, d));
In that case, since d has values for both indexes 0 and 1, none of c's elements are in the result. But:
const c = ["a", "b", "c", "d", "e"];
const d = [2, 3];
console.log(Object.assign([], c, d));
Short answer
When using the spread operator, Regular Objects are ASSIGNED.
When using the spread operator, Arrays are CONCATENATED.
Long Answer
I believe the source of your confusion is that every array in JavaScript is just an object belonging to the Array constructor. So why doesn't joining two or more arrays with the spread operator work the same way as objects do?
Let's analyze what is happening in case of the Object
const a = {'a': 1, 'b': 2};
const b = {'b': 4, 'c': 3};
console.log({...a, ...b}); // Output: { a: 1, b: 4, c: 3 }
console.log(Object.assign({}, a, b)); // Output: { a: 1, b: 4, c: 3 }
console.log({...b, ...a}); // Output: { a: 1, b: 2, c: 3 }
console.log(Object.assign({}, b, a)); // Output: { a: 1, b: 2, c: 3 }
An object is a data structure holding key:value pairs.
Object assignment overwrites the keys with the latest values.
The key b occurs in more than one object and is overwritten with it's latest value. As you can see, if you change the order of the objects spread/assigned, the resulting value of the value of b changes based on the latest object having b.
Now let's come to the Array.
const c = [1,2];
const d = [2,3];
console.log([...c, ...d]); // Output: [ 1, 2, 2, 3 ]
console.log(c.concat(d)); // Output: [ 1, 2, 2, 3 ]
console.log(Object.assign({}, c, d)); // Output: { '0': 2, '1': 3 }
console.log(Object.values(Object.assign({}, c, d))); // Output: [ 2, 3 ]
An array is an object created with the Array constructor which outputs the array as a collection of the values assigned to its keys.
Array concatenation simply joins the arrays.
As you can see above, Object.assign still works on an array because the array is technically an object and it behaves exactly how Object.assign is supposed to work. The keys in this case are simply what we call "index" in an array. This is why when you do array[index] it returns the value, it's the same as object[key] that returns a value. If keys exist, the Object.assign replaces the keys/index with the latest values, else it adds the key-value pair to the object.
Conclusion:
Thus, the difference is how the spread operator works for objects and arrays.
In Objects, spread does Object.assign.
In Arrays, spread does Array concatenation => arrayA.concat(arrayB, arrayC, ...)
Bonus: Set
However, if you want the array to return only unique values, you have to use the Set data structure.
const c = [1,2];
const d = [2,3];
console.log([...new Set([...c, ...d])]); // Output: [1, 2, 3]
console.log(Array.from(new Set(a.concat(b)))); // Output: [1, 2, 3]

Why can't Javascript spread operator be used after object key?

I have the following code:
const array = [{
a: 'a',
b: 'b'
}];
console.log(...array);
const store = {
obj: ...array
}
console.log will print the results just fine. However, when trying to set the key of store I get a Parsing error: Unexpected token.
Isn't ...array a valid object to assign to the obj key of store?
... spreads out array into individual items. Array can have more than 1 element and hence there will be more than 1 RHS and that will be invalid. Hence, you can use obj : {...array} or obj : [...array]
const array = [{a: 'a',b: 'b'},{c: 'c', d: 'd'}];
console.log(...array);
const store = {
obj: {...array},
obj1: [...array]
};
console.log(store);
The spread syntax works inside of objects or iterable. In your case, you need to spread the elements within an array.
Spread Syntax
Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
const array = [0, 1, 2]
const store = {
obj: [...array] // <-- the array is being spreded into an array.
}
console.log(store)

What is the difference between `var in array` and `array.indexOf(var)`?

I am trying to get my head around arrays in JS. My question is; are the following two tests equivalent?
var test = 2;
console.log(test in [1,2,3]);
console.log([1,2,3].indexOf(test) != -1);
They seem to be, but then answers like this and the book I am reading suggest that you can't do in on an array, only on an object. Looking for clarity. There must be a reason that people use .indexOf(x) (which I assume is linear time) and not in (which I assume is constant time).
No. They are completely different.
test in [1,2,3] checks if there is a property named 2 in the object. There is, it has the value 3.
[1,2,3].indexOf(test) gets the first property with the value 2 (which is in the property named 1)
suggest that you can't do in on an array, only on an object
Arrays are objects. (A subclass if we want to use classical OO terminally, which doesn't really fit for a prototypal language like JS, but it gets the point across).
The array [1, 2, 3] is like an object { "0": 1, "1": 2, "2": 3 } (but inherits a bunch of other properties from the Array constructor).
As per MDN,
The in operator returns true if the specified property is in the specified object.
in will check for keys. Its similar to Object.keys(array).indexOf(test)
var a1 = [1,2,3];
var a2 = ['a', 'b', 'c']
var test = 2;
console.log(test in a1)
console.log(test in a2)
// Ideal way
//ES5
console.log(a1.indexOf(test)>-1)
console.log(a2.indexOf(test)>-1)
//ES6
console.log(a1.includes(test))
console.log(a2.includes(test))
The first checks for an index, or if property of an object exists,
console.log(test in [1,2,3]);
and not for a value in the array, as the second is doing.
console.log([1,2,3].indexOf(test) != -1);
The in operator returns true if the specified property is in the
specified object.
Using in operator for an array checks of the indices and the length property - because those are the properties for an array:
console.log(Object.getOwnPropertyNames([1, 2, 3]));
console.log(Object.keys([1, 2, 3]));
console.log('length' in [1, 2, 3]);
Object.keys : return all enumerable properties
Object.getOwnPropertyNames : return all properties
Try this
var test = 2;
var arrval= [1, 5, 2, 4];
var a = arrval.indexOf(test);
if(a>-1) console.log("Having");
else console.log("Not Having");

How to flatten an array of objects into arrays for each object parameter?

I have an array of objects like this:
[
{
p1: 1
p2: 2
},
{
p1: 3
p2: 4
}
]
I would like to flatten this into an array (maintaining order) for each property on the object:
[1, 3] and [2, 4]
Preferably these would be stored in a dictionary with the property as the key:
{
p1: [1, 3],
p2: [2, 4]
}
Is there a non brute force method of doing this in javascript? I am already using both jQuery and Underscore.js if those libraries are any help here.
My current plan is to iterate through all of the objects in the array and manually add each property value to its corresponding array. I'm interested to know if there is more interesting way of doing this.
If the properties are reliably the same on each object, you can use underscore like this.
var keys = _.keys(arr[0]);
var newObj = _.reduce(keys,function(obj,key){
obj[key] = _.pluck(arr,key)
},{});
//newObj will now be in the requested format
If the properties are different on different objects, you'll need to do some additional logic to get the complete list of properties to iterate over.
Something like that:
var result = data.reduce(function(acc, x) {
Object.keys(x).forEach(function(k) {
acc[k] = (acc[k] || []).concat([x[k]])
})
return acc
},{})
console.log(result)
//^ {
// p1: [1, 3],
// p2: [2, 4]
// }
But note that object keys have no order, and the result is up to each implementation. You may have to sort the resulting arrays if you need a specific order.

Should I use curly brackets {} or square brackets [] in this case?

Currently I have an array using an increasing index:
var idx = 1;
var a = [];
a[idx++] = "apple";
a[idx++] = "orange";
...
console.log(a[2]);
And only accessing it by [], not using array specific functions, like length, indexOf, ...
Apparently following is also working in this case:
var a = {};
So, which one should I prefer in such case? For example any performance difference between them?
[ ] denotes an array. Arrays only hold values:
var a1 = [1, 2, 3, 4]
As #Qantas pointed out, array can hold more than just values. An array can even contain another array and/or object:
var a2 = [1, 2, ["apple", "orange"], {one: "grape", two: "banana"}];
{ } denotes an object. Objects have key-value pairs like
var a3 = {one: 1, two: 2}
In your case, it's really a matter of how you would like to be able to access the data. If you are only interested in knowing "apple", "pear", etc. Go ahead and use an array. You can access it via it's index
a1[0]; // outputs 1
a1[1]; // outputs 2
or you can iterate over it with a loop. If you use the curly braces, (given the example I gave) you could access it with
a3.one; // outputs 1
a3["two"]; // outputs 2
It's really up to you on how it would best fit your needs in this case. For a more extensive discussion see this article.
The difference is using square brackets will create an Array object while using curly brackets creates a plain object. For example:
a = [];
a[1] = 'a';
b = {};
b[1] = 'b';
a.length; // returns 2
b.length; // is undefined
a.push('z'); // add 'z' to the end of a
b.push('z'); // generates an error - undefined is not a function
// because plain objects don't have a push method
Read the MDN documentation on Array objects to know more about arrays: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Categories