I can not understand this code - javascript

I had to remove same data in array.
I found this code and its work exactly the way i want but I can not understand part of this code.
please explain this code and WHAT IS THIS >>> a[this[i]] <<<
Array.prototype.unique = function() {
var a = {}; //new Object
for (var i = 0; i < this.length; i++) {
if (typeof a[this[i]] == 'undefined') {
a[this[i]] = 1;
}
}
this.length = 0; //clear the array
for (var i in a) {
this[this.length] = i;
}
return this;
};

Please see the comments before each line that explain that line of code
//added unique function to prototype of array so that all array can have unique //function access
Array.prototype.unique = function() {
//creating a temp object which will hold array values as keys and
//value as "1" to mark that key exists
var a = {}; //new Object
//this points to the array on which you have called unique function so
//if arr = [1,2,3,4] and you call arr.unique() "this" will point to
//arr in below code iterating over each item in array
for (var i = 0; i < this.length; i++) {
//idea is to take the value from array and add that as key in a so
//that next time it is defined. this[i] points to the array item at
//that index(value of i) //and a[this[i]] is adding a property on a
//with name "this[i]" which is the value //at that index so if value
//at that index is lets say 2 then a[this[i]] is //referring to
//a["2"].thus if 2 exists again at next index you do not add it to a
//again as it is defined
if (typeof a[this[i]] == 'undefined') {
a[this[i]] = 1;
}
}
this.length = 0; //clear the array
//now in a the properties are unique array items you are just looping
//over those props and adding it into current array(this) in which
//length will increase every //time you put a value
for (var i in a) {
this[this.length] = i;
}
//at the end returning this which is the modified array
return this;
};
//Edit
stored value of a[this[i]] is 1 for all the keys in a it will be one.
you start with
arr = [1,2,3,2,3,4];
when you call arr.unique
the code in the first loop creates a something like this
a = {
"1":1,
"2":1,
"3":1,
"4":1
}
so you can see that only unique values are as properties in a.
Now in the for-in loop you are just taking the keys of a(ie 1,2,3,4) and adding it to the array(this).
Hope this helps let me know if you need more details

a[this[i]] =>
this[i] -> get i element from current object, in this case it's Array.
a[] -> get element from var a at position specified in [], in this case what value is inside this[i]

Related

Javascript array keys loop through checking

There is an array that contains key value pairs which the key will contain a manipulative id. The problems is that I intend to achieve a concept of checking the key values which is if the key is exist in the array, then the value will check; or else it will create a new key value pairs for the new and unique id. I looked for the Object.keys() function and i find out it will only return array of keys. I tend to check the keys one by one in a for loop tho.
sorry if I did not explain my question well
code:
var marks = new Array();
function totalScore(critId,score){
var compare = Object.keys(marks);
var result = 0;
for(var i = 0; i < marks.length; i++){ //Looping in marks array
for(var j = 0; j < compare.length; j++){ //Looping in compare array
if(compare[j] == marks[i]){ //Comparing the key of the arrays
marks[i] = score; //If matched update the value of the current key
result ++;
}
}
if(result == 0){ //If there are no result of the comparison
marks.critId = score; //Add new key value pair to the array
}
}
}
If I understand your problem correctly, you want to add a new key/value pairs if it doesn't exist.
It's better to use an object or an ES6 Map for this case.
var marks = {};
function totalScore(critId, score) {
if(!(critId in marks)) marks[critId] = score;
}
totalScore(1, 5);
totalScore(2, 8);
totalScore(1, 4);
console.log('marks', marks);

can indexOf work on an updating array?

I understand that there are ways to get unique elements in an array. This question isn't asking about that. This question is asking why indexOf returns -1 for "kale" in the unique_vegetables array once it's already been added. Is there something about indexOf that makes it not work in this situation?
var vegetables = ["kale", "broccoli", "kale"];
function produce(){
var unique_vegetables = [];
unique_vegetables = vegetables.map(function(v){
if (v.length > 0){ //irrelevant check to make sure the string has characters
var k = unique_vegetables.indexOf(v);
return k < 0 ? v : null;
}else {
return null;
}
})
return unique_vegetables;
}
var t = produce();
console.log(t, "unique vegetables") /// ["kale", "broccoli", "kale"]
https://jsfiddle.net/mjmitche/g6nn9nn6/
When you are using Array.map, there are 3 things that make it a whole.
Callback function
Return statement inside callback
Return from .map
Callback is the function that will be called on every iteration and will be passed 3 arguments viz., currentElement, index, and array itself.
Return from callback will initialize the value of this iteration in return array. This return array is a local array in .map and will not be accessible to you.
Return from map is the final step that returns the parsed local array pointed out in previous step.
Array.map would look something like this in simple implementation:
function myMap(arr, callback){
var temp = [];
for(var i = 0; i< arr.length; i++){
temp[i] = callback(arr[i], i, arr);
}
return temp;
}
var a = [1,2,3,4,5];
var b = myMap(a, function(n, i, a){ return n * 2 })
console.log(b)
Reference
Polyfill - MDN: You can refer it to check the actual code.
vegetables.forEach(function(v){
if (v.length > 0){
var k = unique_vegetables.indexOf(v);
if(k < 0) unique_vegetables.push(v);
}
})
unique_vegetables is an empty array until the map function finished and returned, so you need to change unique_vegetables while iterating.

Javascript - nested loops and indexes

I am trying to build an array that should look like this :
[
[{"name":"Mercury","index":0}],
[{"name":"Mercury","index":1},{"name":"Venus","index":1}],
[{"name":"Mercury","index":2},{"name":"Venus","index":2},{"name":"Earth","index":2}],
...
]
Each element is the concatenation of the previous and a new object, and all the indexes get updated to the latest value (e.g. Mercury's index is 0, then 1, etc.).
I have tried to build this array using the following code :
var b = [];
var buffer = [];
var names = ["Mercury","Venus","Earth"]
for (k=0;k<3;k++){
// This array is necessary because with real data there are multiple elements for each k
var a = [{"name":names[k],"index":0}];
buffer = buffer.concat(a);
// This is where the index of all the elements currently in the
// buffer (should) get(s) updated to the current k
for (n=0;n<buffer.length;n++){
buffer[n].index = k;
}
// Add the buffer to the final array
b.push(buffer);
}
console.log(b);
The final array (b) printed out to the console has the right number of objects in each element, but all the indexes everywhere are equal to the last value of k (2).
I don't understand why this is happening, and don't know how to fix it.
This is happening because every object in the inner array is actually the exact same object as the one stored in the previous outer array's entries - you're only storing references to the object, not copies. When you update the index in the object you're updating it everywhere.
To resolve this, you need to create new objects in each inner iteration, or use an object copying function such as ES6's Object.assign, jQuery's $.extend or Underscore's _.clone.
Here's a version that uses the first approach, and also uses two nested .map calls to produce both the inner (variable length) arrays and the outer array:
var names = ["Mercury","Venus","Earth"];
var b = names.map(function(_, index, a) {
return a.slice(0, index + 1).map(function(name) {
return {name: name, index: index};
});
});
or in ES6:
var names = ["Mercury","Venus","Earth"];
var b = names.map((_, index, a) => a.slice(0, index + 1).map(name => ({name, index})));
Try this:
var names = ["Mercury","Venus","Earth"];
var result = [];
for (var i=0; i<names.length; i++){
var _temp = [];
for(var j=0; j<=i; j++){
_temp.push({
name: names[j],
index:i
});
}
result.push(_temp);
}
console.log(result)
try this simple script:
var b = [];
var names = ["Mercury","Venus","Earth"];
for(var pos = 0; pos < names.length; pos++) {
var current = [];
for(var x = 0; x < pos+1; x++) {
current.push({"name": names[x], "index": pos});
}
b.push(current);
}

Creating dynamic objects to a parent object and assigning keys and values?

I am almost there with this but cannot seem to get this functionality going as planned.
I have two arrays: keyArray and ValArray;
What I am trying to do is to have a function pass two arguments (keyArr,valArr). Within this function, a parent object is declared and a (for-loop) loops through the passed argument's length (in this case "keyArr") creates new objects according the length of the passed argument. And then, the newly created objects are assigned the keys and values.
The issue is that I am able to create the parent object"mObj", and children Objects to "mObj", but am only able to assgin keys and values to the first child object "obj0" not rest of the children objects correctly. At the end of the code, this is what I would like to get:
enter code heremObj.obj0.firstname = John;
mObj.obj0.lastname = superfly;
mObj.obj0.email = "john.superfly#yahoo.com";
mObj.obj1.firstname = John;
mObj.obj1.lastname = superfly;
mObj.obj1.email = "john.superfly#yahoo.com";
mObj.obj2.firstname = John;
mObj.obj2.lastname = superfly;
mObj.obj2.email = "john.superfly#yahoo.com";
This is my code:
var keyArr = ["firstname","lastname","email"];
var valArr = ["John","Superfly","jsuperfly#yahoo.com"];
function test(keys,vals) // FUNCTION TEST ACCEPTS TWO ARGS
{
var mObj = {}; // PARENT OBJECT
var len = (keys.length); //ARGUMENT KEY'S LENGTH
for(var i=0; i<len; i++)
{
mObj["obj" + i] = {}; //CHILDREN OBJECTS ARE CREATED TO PARENT "mObj" OBJECT
mObj["obj" + i][keys[i]] = vals[i]; //KEYS AND VALUES ARE ASSIGNED HERE
}
alert(mObj.obj1.firstname); // CURRENTLY RETURNS "UNDEFINED"
}
test(keyArr,valArr);
Any insight into this would highly be appreciated.
Thank you.
Seems like this is what you need. This code will create as many child objects as the length of keyArr and valArr arrays. Although no idea why you would need it.
var keyArr = ["firstname", "lastname", "email"];
var valArr = ["John", "Superfly", "jsuperfly#yahoo.com"];
function test(keys, vals) {
var mObj = {},
i, j, len = keys.length;
for (i = 0; i < len; i++) {
mObj["obj" + i] = {};
for (j = 0; j < len; j++) {
mObj["obj" + i][keys[j]] = vals[j];
}
}
alert(mObj.obj1.firstname);
}
console.log( test(keyArr, valArr) );​

JavaScript: convert objects to array of objects

I have thousands of legacy code that stores array information in a non array.
For example:
container.object1 = someobject;
container.object2 = someotherobject;
container.object3 = anotherone;
What I want to have is:
container.objects[1], container.objects[2], container.objects[3] etc.
The 'object' part of the name is constant. The number part is the position it should be in the array.
How do I do this?
Assuming that object1, object2, etc... are sequential (like an array), then you can just iterate through the container object and find all the sequential objectN properties that exist and add them to an array and stop the loop when one is missing.
container.objects = []; // init empty array
var i = 1;
while (container["object" + i]) {
container.objects.push(container["object" + i]);
i++;
}
If you want the first item object1 to be in the [1] spot instead of the more typical [0] spot in the array, then you need to put an empty object into the array's zeroth slot to start with since your example doesn't have an object0 item.
container.objects = [{}]; // init array with first item empty as an empty object
var i = 1;
while (container["object" + i]) {
container.objects.push(container["object" + i]);
i++;
}
An alternate way to do this is by using keys.
var unsorted = objectwithobjects;
var keys = Object.keys(unsorted);
var items = [];
for (var j=0; j < keys.length; j++) {
items[j] = unsorted[keys[j]];
}
You can add an if-statement to check if a key contains 'object' and only add an element to your entry in that case (if 'objectwithobjects' contains other keys you don't want).
That is pretty easy:
var c = { objects: [] };
for (var o in container) {
var n = o.match(/^object(\d+)$/);
if (n) c.objects[n[1]] = container[o];
}
Now c is your new container object, where c.object[1] == container.object1

Categories

Resources