Output all values of a Set of strings - javascript

In JavaScript, what is the shortest code to output, for debugging purposes, all elements of a Set of strings? It doesn't matter if the strings are on one line or individual lines.
const set = new Set();
set.add('dog');
set.add('cat');
console.log(???);

You can use 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 set = new Set();
set.add('dog');
set.add('cat');
console.log(...set);

You can create an Array out of the Set, then log that:
const set = new Set();
set.add('dog');
set.add('cat');
console.log(Array.from(set));

You can use the ES6 method
.forEach()
So in full:
const set = new Set();
set.add('dog');
set.add('cat');
set.forEach(item => console.log(item))

Related

What is the different vs array.push() and array = [...array, newItem]?

I have seen some YouTubers not use array.push() to add items to an array but rather do something like:
let item = 3
let array = [1, 2];
array = [...array, item]; // Why not use array.push()?
Is there any difference between the two methods and which one should i use?
Push: Use push when you want to add data in the existing array and don't want to cra
When you use the push method, you are adding the element to the existing one i.e not creating a new array.
The push() method adds one or more elements to the end of an array and
returns the new length of the array. - MDN
const arr = [1, 2, 3, 4, 5];
const returnValue = arr.push(6);
console.log(arr);
console.log(returnValue)
Spread Syntax: Use spread syntax if you want to add elements in new array(it can be from spread or can add more new elements also) but will create a new array []
This is called 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.
let array = [1, 2];
let item = 3
result = [...array, item];
console.log(result === array);
In the above snippet you are creating a new array and assigning values 1, 2 then you are using spread syntax to spread it into a new array. You can also add new elements also like item whose value is 3.
array.push manipulates the existing array. The latter makes a new copy with the new value.
Array push is used to push items kn exisiting array but if we want a copy of an element of an array as a new array variable- you can use […array] operator.

How do I add the same element to an array multiple times?

I'm making shopping cart,and I am a little bit confused. There is a counter which counts number of current product. For example: the user can buy 5 book or more. So , I need to make a function which adds the element аs many times as the user will select it.
I made something like this:
[...state.shoppingCart, new Array(state.booksNumber).fill({...action.book})]
But of course it makes a new array in array... So how can I just add elements to an array without deleting old elements or creating a new array inside the array?
I need a functional way, no loops.
const newArray = new Array(state.booksNumber).fill({...action.book})
[...state.shoppingCart, ...newArray]
Simply use the spread syntax again:
[...state.shoppingCart, ...new Array(state.booksNumber).fill({...action.book})]
That will spread the new array into the existing array.
You can use the concat method
const a = new Array([1,3,4]).concat([1,3,4])
console.log(a)
This will add the elements into the array.
Or you can try with spread operator.
const arr=[1,2,3,4]
const a = new Array([1,3,4,.... arr]);
console.log(a)
You are missing the spread operator inside the returning array for the new Array you created.
Adding the spread operator allows you to merge/concat both array items.
For example:
const arrayOne = [1,2,3];
const arrayTwo = [4,5,6];
const mergedArrays = [...arrayOne, ...arrayTwo] //[1,2,3,4,5,6]
Also assuming action.book is an object you want to add multiple times inside of the new Array() you've created, there is no need to spread it as it will fill the array with each object.
This function might help out with what you are looking for:
const addMultipleItems = (action) => {
const items = new Array(state.booksNumber).fill(action.book);
return [...state.shoppingCart, ...items];
}

Javascript "Set" for Objects and Arrays

Does Javascript have a built-in type for making a set out of data-objects and arrays?
let set = new Set();
set.add({"language": "ecmascript"});
set.add({"language": "ecmascript"});
set.add({"language": "ecmascript"});
set.add({"language": "ecmascript"});
set.add([1,2,3]);
set.add([1,2,3]);
set.add([1,2,3]);
set.add([1,2,3]);
console.log(set);
The Set I'm using above is only useful for primitives.
The Set I'm using above is only useful for primitives.
That's incorrect, it works just fine for objects. The problem is that distinct objects with the same properties and property values are not equal, so doing set.add({"language": "ecmascript"}); twice adds two non-equal objects to the set (both with the same property name and value).
If you add the same object more than once, it won't be added a second time:
const set = new Set();
const obj = {"language": "ecmascript"};
set.add(obj);
set.add(obj);
console.log(set.size); // 1
Does Javascript have a built-in type for...
If you want objects with the same properties and values to be treated as equal, then no. You'd need to be able to specify a comparison operation, and there's no built-in Set in JavaScript that lets you define the comparison operation to use.
Obviously, you can create one. As a starting point, I'd probably use a Map keyed by the names of the properties on the object, sorted and turned into a string via JSON.stringify. (Although that won't work if you want to have Symbol keys as part of the definition of equality.) For instance, if you're only considering own properties:
const key = JSON.stringify(Object.getOwnPropertyNames(object).sort());
The value for an entry could be either just an array of the objects with those keys that you do a linear search on, or a second Map keyed by some kind of hash of the property values, depending on how many objects you need to handle...
In comments, I asked:
Do you only need to handle objects with JSON-serializable values?
and you answered:
I have a bunch of objects that are already serialized, but there are duplicates that I'd like to eliminate and then re-serialize.
Yeah, you can use a Set for that if you don't mind re-serializing, or a Map if you want to skip the re-serializing part:
const unique = new Map();
for (const source of serializedObjects) {
const sourceObject = JSON.parse(source); // Or parse from whatever serialization it is
// Build object adding properties in alpha order for stability
const keyObj = {};
for (const key of Object.keys(sourceObject).sort()) {
keyObj[key] = sourceObject[key];
}
// Save it using JSON.stringify, which uses ES2015 property order
map.set(JSON.stringify(keyObj), source);
}
const uniqueSourceStrings = [...map.values()];
Or for the de-serialized objects themselves:
const unique = new Map();
for (const source of serializedObjects) {
const sourceObject = JSON.parse(source); // Or parse from whatever serialization it is
// Build object adding properties in alpha order for stability
const keyObj = {};
for (const key of Object.keys(sourceObject).sort()) {
keyObj[key] = sourceObject[key];
}
// Save it using JSON.stringify, which uses ES2015 property order
map.set(JSON.stringify(keyObj), sourceObject); // <=================== changed
}
const uniqueSourceObject = [...map.values()];
// ^^================================================================== changed

How to initialize array length and values simultaneously in new Array()?

Let’s consider, I have to initialize an Array with some values
So I can achieve this by writing following code.
var arr = new Array("a", "b", "c", "d")
console.log(arr)
Similarly, I have to determine the length of the array before using it.
So I can achieve this by following code.
var arr = new Array(5)
console.log(arr.length)
Finally, I have a following questions ?
Is it possible to initialize an array with array length and different values (not similar values) simultaneously using new Array() ?
How to initialize a single integer value using new Array() ?
EDIT:
here, different values refers there are some specific string values.
I know it is straightforward when using array literals. but that's not exactly what I want.
The answer for both questions is no. Looking at the docs, there are two overloads for the Array function.
A JavaScript array is initialized with the given elements, except in the case where a single argument is passed to the Array constructor and that argument is a number (see the arrayLength parameter below).
If the only argument passed to the Array constructor is an integer between 0 and 232-1 (inclusive), this returns a new JavaScript array with its length property set to that number.
Only these two possibilities exist, there is no overload for specifying both the size and the values of an array.
You can create and fill an array like so:
let a = Array(100).fill(null)
console.log(a)
Or to increment your filled values:
let i=0,a = Array(100).fill(0).flatMap(x=>[x+i++])
console.log(a)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
You could use .fill().
console.log(new Array(5).fill(2));
// [2, 2, 2, 2, 2]
Is it possible to initialize an array with array length and values simultaneously using new Array() ?
As far as I know, this isn't possible yet.
How to initialize a single integer value using new Array() ?
That would be k => new Array(1).fill(k). But if I had to choose, I'd use k => [k]. Note it is recommended not to use new Array() in other scenarios than to initialize it's lenght. But even then, you should rather be sure you are giving it an integer because the behaviour of new Array(n) is a bit erratic, and won't throw you an error when you wish it did.
Actually, I wish it was not possible to initialize an array with value using new Array(). The worst being using new Array(...args), whose behaviour will change dramatically when args is [5]. You should stick to [] arrays if you want to initialize an array with values.
Array("") gives [""]
Similarly Array([]) gives [[]] and Array({}), [{}]
Array(5) gives an array with 5 empty slots
Array(2.5) produces an Uncaught RangeError: Invalid array length.
Also, Array() gives []
Note: This is Chromium's behaviour. I didn't check Firefox.
There are few ways to create an array:
1) Literals
const a = [1,2,3];
console.log(a);
But you say you don't want to use it.
2) Array constructor:
const a = new Array(10); //array of length 10
console.log(a);
const b = new Array(1,2,3);
console.log(b); // array with elements 1,2,3
But you say that you don't want to go for it
3) Array.from
const a = Array.from(new Array(10), (val, ind) => ind); // array of 10 values and map applied to these elements
console.log(a);
Over these 3 ways, you have the Array.fill method, which can be called with static values only:
const a = new Array(10);
console.log(a.fill(5)); // array of 10 number elements with value of 5
Considering your case, maybe your solution could be to go with Array.from, using the map function you can provide as second parameter.
You could think to create some function like the following:
function createMyArray(length, start, end) {
return Array.from(new Array(length), (val, ind) => ind >= start && ind <= end ? ind : undefined);
}
console.log(createMyArray(5, 2, 4));
console.log(createMyArray(5, 1, 3));
console.log(createMyArray(10, 2, 6));
The question you should ask to yourself is: Where and how is the data I want to use coming from? Otherwise this is really too much vague
Is it possible to initialize an array with array length and different values (not similar values) simultaneously using new Array() ?
No you cannot do that with the Array constructor only.
An alternative way is to do it like this:
var a = ['a', 'b', 'c', 'd'];
a.length = 10;
console.log(a);
How to initialize a single integer value using new Array() ?
You can't. This is what happens when you try to do so according to the specification:
Array(len)
[...]
Let intLen be ToUint32(len).
If intLen ≠ len, throw a RangeError exception.
Let setStatus be Set(array, "length", intLen, true).
Assert: setStatus is not an abrupt completion.
Return array.
Use the other ways to create an array instead (e.g. [1] or Array.of(1)).
Here's a different but related take on initializing an array without using an array literal.
let arr = [...Array(10)].map((emptyItem, index) => index);
// [0,1,2,3,4,5,6,7,8,9]
I can't find documentation that matches how this expression is constructed, so I can't fully explain it. But it is using the spread syntax to spread 10 empty items into an array.

How to convert Map keys to array?

Lets say I have the following map:
let myMap = new Map().set('a', 1).set('b', 2);
And I want to obtain ['a', 'b'] based on the above. My current solution seems so long and horrible.
let myMap = new Map().set('a', 1).set('b', 2);
let keys = [];
for (let key of myMap)
keys.push(key);
console.log(keys);
There must be a better way, no?
Map.keys() returns a MapIterator object which can be converted to Array using Array.from:
let keys = Array.from( myMap.keys() );
// ["a", "b"]
EDIT: you can also convert iterable object to array using spread syntax
let keys =[ ...myMap.keys() ];
// ["a", "b"]
You can use the spread operator to convert Map.keys() iterator in an Array.
let myMap = new Map().set('a', 1).set('b', 2).set(983, true)
let keys = [...myMap.keys()]
console.log(keys)
OK, let's go a bit more comprehensive and start with what's Map for those who don't know this feature in JavaScript... MDN says:
The Map object holds key-value pairs and remembers the original
insertion order of the keys.
Any value (both objects and primitive
values) may be used as either a key or a value.
As you mentioned, you can easily create an instance of Map using new keyword...
In your case:
let myMap = new Map().set('a', 1).set('b', 2);
So let's see...
The way you mentioned is an OK way to do it, but yes, there are more concise ways to do that...
Map has many methods which you can use, like set() which you already used to assign the key values...
One of them is keys() which returns all the keys...
In your case, it will return:
MapIterator {"a", "b"}
and you easily convert them to an Array using ES6 ways, like spread operator...
const b = [...myMap.keys()];
I need something similiar with angular reactive form:
let myMap = new Map().set(0, {status: 'VALID'}).set(1, {status: 'INVALID'});
let mapToArray = Array.from(myMap.values());
let isValid = mapToArray.every(x => x.status === 'VALID');
Not exactly best answer to question but this trick new Array(...someMap) saved me couple of times when I need both key and value to generate needed array. For example when there is need to create react components from Map object based on both key and value values.
let map = new Map();
map.set("1", 1);
map.set("2", 2);
console.log(new Array(...map).map(pairs => pairs[0])); -> ["1", "2"]
Side note, if you are using a JavaScript object instead of a map, you can use Object.keys(object) which will return an array of the keys. Docs: link
Note that a JS object is different from a map and can't necessarily be used interchangeably!

Categories

Resources