This is my last post about Data Structures, I swear. Besides, there's not much more I could post about this topic since I already went down the rabbit hole with this one, so no more DS from me. I gotta say this topic has been the most complicated and obnoxious to learn in my whole JS oddysey and it took me a long time to get all the concepts understood and stored into my long term memory side of the brain, whatever that may be but hey, at least I had fun with it.
It's been around 110 hours into JavaScript for me now, not much considering that these past two months had 660 available hours after taking off eating, sleeping and exercising; well, I guess I could take off 60 more hours because I've been writing one post per day and that usually takes like 1 hour per day, but still, I'm at around 17% of efficiency and I should be around 60%. I mean I have to take some time off for the girlfriend and for playing chess right?
I would need to be putting in around 300 hours per month into this, otherwise I'm not going to reach my goals and deadlines (self set, in case you're wondering).
Anyway, let's get to business.

Sets
JavaScript only had built in data structures through arrays, but in ES6 sets and maps were intriduced. These two already existed in other programming languages but JS lacked them.
A set is a collection of uniqwue values, there can't be duplicates in a set.
A set can hold any type of data.
const ordersSet = new Set(["pasta", "pizza", "pizza", "risotto", "pizza"]); // 1
console.log(ordersSet);
1.To create a new set we have to write this and then pass an array into it.
Output: Set(3) { 'pasta', 'pizza', 'risotto' }
We only get these 3 values because all the duplicates are gone. A set looks like an array, with no key values.
Sets are also iterables, but the order of the elements is irrelevant.
Do you remember that string are also iterables? Well, we can also create a set with the letters of a string:
console.log(new Set("Eric"));
Output: {"E", "r", "i", "c"}
We can get the size of a set with the same logic or array.length
console.log(orderSet.size);
Output: 3
We can check if an element is in a set, similar to the .include method
console.log(orderSet.has("Pizza")); // Output: True
console.log(orderSet.has("Bread")); // Output: False
We can add new elements to a set, just like the .push method
orderSet.add("Garlic Bread");
We can also delete elements, just like the .pop method
orderSet.delete("Risotto");
To delete all the elements from a set we just
orderSet.clear;
To retrieve value from a set is a little bit trickier concept because we can't use indexes because as I said, sets have no order or index. In reality, there's not a real use case for getting values out of a set. But the cool part of sets is that despite this fact, we can actually loop through them.
for(const order of orderSet) console.log(order); Output: { 'pasta', 'pizza', 'risotto' }
Use cases for Sets
Removing duplicate values from arrays
const staff = ["writer", "developer", "manager", "developer"];
Let's say that for some reason we only want to know how many different positions we have at the company, not how many people. We create a set for that.
const staffUnique = new Set(staff);
But this won't output them in an array form, we have to use the spread operator to create the array. This will actually output them in array form.
const staffUnique = [...new Set(staff)];
console.log(staffUnique.size); // *
*To know the size of the set by using the declared variable above
Maps: Fundamentals
Maps are more useful than sets, but hold similarities with them. A map is a data structure that we can use to map values to keys, data is store in key value pairs like in an object, but in maps the keys can have any type. In objects the keys are necessarily strings, but in maps we can have objects as keys, or even a map as a key of a map.
const hive = new Map(); // 1
hive.set("name", "Hive Ecosystem"); // 2
hive.set(1, "Hive");
hive.set(2, "HBD"); // 3
1.The easiest way to create a map is to leave the constructor empty, without passing it values and then fill it up using the .set method.
2.The .set method is similar to the .add method for sets. It allows us to add a new element (of any data type) to the data structure.
3.Calling the set method like this updates the map that it is called on, and returns the map
Output:
The fact that the .set method returns the updated map, allows us to chain the .set method like this:
hive
.set("dApps", [
"Leo Finance",
"Actifit",
"Peakd",
"Pinmapple",
"Ecenecy",
"Splinterlands",
])
.set("Max vote %", "100")
.set("Min vote %", "2") // The values can be anything
.set(false, "You can't cast a 100% vote")
.set(true, "Go ahead and give a full vote!");
In order to read data from a map we use the .get method
console.log(hive.get("name")); // All we need to do is to pass in the name of the key
The data type of the key matters. If we call the key true we will get the value, but if we call 'true' as a string, we will get undefined, because the value is linked to the boolean true, not the string true.
/Now that we know this, let's try to play around with the boolean keys regarding voting power.
We want to know if a user has enough voting power to cast a 100% vote, so we have to compare the current voting power of the user with the Min/Max keys, and then call the corresponding boolean with the string value.
const currentVP = 91;
console.log(
hive.get(
currentVP > hive.get("Min vote %") && currentVP < hive.get("Max vote %") *
)
);
* The result of these two cases will result in true or false, and then the true or false will return the corresponding string value.
Output: Go ahead and give a full vote!
The way I wrote this code is kinda clever, but one can get lost in it, it's code that it's not that easy to read, my reccommendation is to not use it too often.
We saw how we can set and get keys and values, but we can also check if the map contains a certain key.
console.log(hive.has("dApps")); // Output: true
We can also delete elements from the map based on the key. Let's say that at one point we eliminate the Hive Dollar from the Ecosystem.
hive.delete(2); *
*The key that corresponds to HBD is no longer part of the map.
There is also a size property for maps.
console.log(hive.size); // 7
We can also remove all the elements from the map with the .clear method.
hive.clear();
As I mentioned, we can use arrays and objects as map keys, check it out.
hive.set([1, 2], "Test");
console.log(hive); // output: Map(1) { [ 1, 2 ] => 'Test' }
But to get the data based on that array key we need to think, check this out:
hive.set([1, 2], "Test");
console.log(hive.get([1, 2])); // We will get undefined, not a real value.
This happens beause even though we are calling the array key using literally the same syntax [1, 2], remember that arrays and objects are stored in the memory heap, which means the array we used to call it and the array we called, are actually not the same object. To make it work like that, we need to store the array in a string and then use the string to add the key to the map, that way the string will be stored in the call stack and not in the heap.
const array = [1, 2];
hive.set(array, "Test"); // *
console.log(hive.get(array)); // Test
Now these two (arr*) refer to the same place in the memory stack.
Calling values of a map with object keys is very useful when working with DOM elements (which are objects in the end)
There is also a different way to populate a new map without using the .set method. We will pass in an array that contains multiple arrays, where the first position is the key, and the second position is the value:
const question = new Map([
["question", "Which is the dApp most used on Hive as of November 2021?"],
[1, "Actifit"],
[2, "Splinterlands"],
[3, "Leo Finance"],
["correctAnswer", 3],
[true, "Correct!"],
[false, "Try again!"],
]);
console.log(question);
When we create a new map from scratch, this way of populating a map is more efficient if we are doing simple and short maps, but when we need to keep adding elements frequently, the .set method is the way to go.
A map is very similar to an object, and there is actually a way to convert objects into maps just by storing a new map into a new string:
const newMap = new Map(Object.toString(keyFromObject))
Iterations on Maps
Maps are also iterables and we can use for loops on them.
console.log(question.get("question"));
for (const [key, value] of question) { // 1
// 2
if (typeof key === "number") console.log(`Option ${key}: ${value}`);
}
const answer = Number("Your answer"); // 3
console.log(answer);
1.Each item of the map will contain both the key and the value. We are destructuring the keys and values into separate values between the [] directly inside the loop.
2.I only want to print the anwser options, so I need to specify that I only want the keys and values when said key is a number.
3.We convert the Answer to number type so we can compare it to the three option keys.
Now we need to compare the answer to the options and the correctAnswer using the Boolean keys.
question.get("correctAnswer") === answer; // 1
// 2
console.log(question.get(question.get("correctAnswer") === answer)); // 3
1.This is a clean way to write and if case statement, and if it is true, we will return the value of the boolean key true, if it isn't, we'll returnt the value from the false key.
2.We just compared the answers and the value can or cannot be true, but we still need to plus that into the map so we can get either value depending on the key
3.This is an implicit way of calling the True or False boolean key from the map, because we wrote a clean IF statement that returns either True or False, and then based on that return vale, we will call that boolean key from the map, get it?
As a side note, if you need convert a map into an array, you can unpacking the map and using the spread operator.
console.log([...question]);
It's not that common and I yet need to find a reason to try to convert a map into an array, but at least now we know how to do it.
To finish, I'll just list the most common methods to get information from maps.
question.entries();
question.keys();
question.values();
Deciding which Data Structure to use
Data can come basically from three sources:
- Source code: Data written by us in the code
- User interface: Inputs from the user or data written in the DOM
- External Sources: Usually APIs (Application Programming interface).
We usually have collections of Data that we need to store, and we use Data Structures to do that.
To decide what Data Structure to use we have to ask us what type of Data we have and the way we want to organize it.
If we just need a simple list of values we can use an array or a set. If we need key and value pairs, we use an object or map. The big difference is that with a key/value piar, we can describe the values. In a list we simply have the values without any description.
Data that comes from APIs come in a Data Format called JSON. JSON is like a long string but it can be converted to an object because it uses the same formatting as objects and arrays.
There are more Data Structures like weak sets and weak maps but I'm not gonna go into these, I'll focus in the main four.
When to use which DS?
- Arrays - When we don't need to store described values. When we need to manipulate data because there are many many methods.
- Sets - When we are working with unique values. When high-performance is a priority because operations like searching or deleting items are wayy more faster than with Arrays. We can also remove duplicate values.
Sets are not on JS to replace arrays but to complement them when dealing with unique values.
- Objects - This is the tradicitional key/value store. They are easier to write and access values with . and []. When you need to include functions (methods) and when working with JSON, because they can be converted to maps.
- Maps - They offer better performance and are better suited for simple key/value stores. Map keys can have any data type, they are easier to iterate and easy to compute the size of them. When you need keys that are not strings.
And finally, I'm all done with Data Structures. I mean, not for life but at least for a while, I'm now gonna dedicate to go into the rabbit hole with Strings.
Thanks for reading, I hope you liked it and you found this post useful!