How to clone an item of objects in array? - javascript

I have an array as given below -
var x = [{
name: "Mr.X",
age: 22
},{
name: "Mr.Y",
age: 26
},{
name: "Mr.Z",
age: 24
},];
I want to duplicate the 2nd item and put it as the first element. Just to avoid any confusion, I want the resultant array to be as given below -
var x = [{
name: "Mr.YD",
age: 19
},{
name: "Mr.X",
age: 22
},{
name: "Mr.Y",
age: 26
},{
name: "Mr.Z",
age: 24
},];
What I have tried and got - I extracted the 2nd item, and changed the name and age properties. But it is also changing the 2nd item. I know it is because we are changing the reference. But i have no idea how to extract/duplicate item and change only its value.

if you are looking for clone of the object
there are multiple ways
jQuery Extend:
// Shallow copy
var newObject = jQuery.extend({}, oldObject);
// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);
JSON Stringify
var newObject = JSON.parse(JSON.stringify(oldObject))
Or :
Write a clone method by iterating through object props recursively
Then append to the array using the standard array APIs

var x = [{
name: "Mr.X",
age: 22
},{
name: "Mr.Y",
age: 26
},{
name: "Mr.Z",
age: 24
},];
console.log(x);
var y = JSON.parse(JSON.stringify(x));
y.unshift({
name: "Mr.XD",
age: 19
});
console.log(y);
Unshift appends on top of array
Push appends on the end of array

Related

Accessing duplicates in objects in the same array?

I have an array with multiple objects
arr = [
{name: 'xyz',
age: 13,
},
{name: 'abc',
age: 15,
},
{name: 'abc',
age: 15,
}]
how do I find the duplicate in this array and remove the object that is duplicated in the array? They are all in one array.
Apologies. I just realized what I am trying to do is, remove the object entirely if there's a duplicate in one key... so if the age is similar, I will remove object name "def". Is this possible?
arr = [
{name: 'xyz',
entry: 1,
age: 13,
},
{name: 'abc',
entry: 2,
age: 15,
},
{name: 'def',
age: 13,
entry: 3
}]
You could achieve this by the following steps:
transform each element into an object that is key-sorted, this will make objects consistent in terms of key-value pairs order, which will help us in the next step
map the array into JSON-stringified value, and store it into a Set(), which would help us store only unique stringified objects
turn the Set() back into array
map the array back into objects by JSON.parse() each element
const arr = [
{ name: "xyz", age: 13 },
{ age: 15, name: "abc" },
{ name: "abc", age: 15 },
]
const sortKeys = obj =>
Object.fromEntries(
Object.entries(obj).sort((keyValuePairA, keyValuePairB) =>
keyValuePairA[0].localeCompare(keyValuePairB[0])
)
)
const res = Array.from(
arr
.map(sortKeys)
.map(el => JSON.stringify(el))
.reduce((set, el) => set.add(el), new Set())
).map(el => JSON.parse(el))
console.log(res)
References
Set
Object.entries()
Object.fromEntries()

need to convert object into array

const obj = {
obj1: [{
name: 'Max',
age: 25
}]
}
Object.values(obj).map(obj => console.log(obj.obj1.name))
Uncaught TypeError: Cannot read property 'name' of undefined. I need to get that name
If you are just trying to loop through the object values, using forEach instead of the map is a good idea. Map returns a new array but forEach doesn't. Also, Object.values() will return an array of all the values in the object(each value is an array of objects in this case). Therefore, using 2 forEach loops makes the task easier.
const obj = {
obj1: [{
name: 'Max',
age: 25
}],
obj2: [{
name: 'Min',
age: 26
}]
}
Object.values(obj).forEach(mainObj => mainObj.forEach(obj => console.log(obj.name )))
You are trying to access the wrong key. Your object has a key obj1 which is an array. You have to loop through that array as well.
const obj = {
obj1: [{
name: 'Max',
age: 25
}],
obj2: [{
name: 'Min',
age: 24
}]
}
var objectValuesArr = Object.values(obj)
var particularObj = objectValuesArr.map(obj => obj.forEach(obj => console.log(obj.name)))

How to remove duplicates from an array using forEach method in javascript

I have an array in that I have objects and strings now my goal is to filter all duplicates from strings and objects.
If you don't understand, please put a comment
const data = [
'apple',
'mango',
'orange',
'grapes',
'apple',
'mango',
{
name: 'Mark',
age: 28
},
{
name: 'Mark',
age: 28
},
{
name: 'James',
age: 28
},
'sapota',
'gaua',
{
name: 'Williams',
age: 26
},
{
name: 'John',
age: 24
},
'gaua'
]
console.log(data)
One method you could use assuming you have no circular data structures
function removeDup(arr){
let known = [];
return arr.filter(elem => {
let str = JSON.stringify(elem); // Get string of whatever item we are dealing with
if(!known.includes(str)){ //Check to see if we have seen this item before
known.push(str); //If we havnt add it to seen list
return true;
}
return false;
});
}
Obviously this is constrained to anything that JSON.stringify can handle.
Also, this method assumes that in an array like:
[{name: 'name'}, 'name']
the two names are different things and will both get returned. If you want to treat them the as duplicates let me know
Note this doesn't use a forEach loop but could VERY easily be change to use one.

How to extract values from certain keys from objects that are in an array

I have this array of objects:var array = [{name: "Tom", id: 123}, {name: "chris", id: 1234}, {name: "Simon", id: 111}];
I want to iterate through the 3 objects in the array and extract the name of each one, and then push that name into a new array.
This is what I thought would work:
var array = [{name: "Tom", id: 123}, {name: "chris", id: 1234}, {name: "Simon", id: 111}];
var newArrayOfNames = [];
Object.values(array).forEach(function(name){
newArrayOfNames.push(name);
});
console.log(newArrayOfNames);
you can try this:
var array = [{name: "Tom", id: 123}, {name: "chris", id: 1234}, {name: "Simon", id: 111}];
var newArrayOfNames = [];
array.forEach(function(item) {
newArrayOfNames.push(item.name);
});
console.log(newArrayOfNames);
A small change to your code:
var array = [{name: "Tom", id: 123}, {name: "chris", id: 1234}, {name: "Simon", id: 111}];
var newArrayOfNames = [];
Array.prototype.forEach.call(array, function(o){
newArrayOfNames.push(o.name);
});
console.log(newArrayOfNames);
let array = [{name: "Tom", id: 123}, {name: "chris", id: 1234}, {name: "Simon", id: 111}];
let names = []
for(let person of array) {
names.push(person.name)
}
This should work, it takes the name attribute from the "person", which is in this case an entry in your array.
IMHO, the best approach as of 2021 is as follows:
let array = [
{
name: "Tom",
id: 123
},
{
name: "chris",
id: 1234
},
{
name: "Simon",
id: 111
}
];
// Use the Array's map function to transform the elements of the array into something else
let newArrayOfNames = array.map( pValue => pValue.name );
console.log( newArrayOfNames );
The map's documentation states:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
This would be the most appropriate way (Provided you don't support IE anymore or you use a transpiler) since both arrays are of the same length.
If you need to omit elements I'd use the filter function for omitting those elements first and then the map function, and although that requires to iterate once through the original array and once through the filtered array, the purpose of the code is clearer for the reader of the code. Another approach is to use reduce to create another array and filter the elements in the callback given to reduce (not pushing them into the new array), this will only traverse the original array once but may lack clarity for readers depending on your code.
A small change in your existing code would have worked:
var array = [{name: "Tom", id: 123}, {name: "chris", id: 1234}, {name: "Simon", id: 111}];
var newArrayOfNames = [];
Object.values(array).forEach(function(person){ // note that person is the object on each iteration of array
newArrayOfNames.push(person.name); // object has property called name
});
console.log(newArrayOfNames); // => [ "Tom", "chris", "Simon" ]
This is the perfect use case for a .reduce(), whose goal is:
The reduce() method applies a function against an accumulator and each
element in the array (from left to right) to reduce it to a single
value.
In your case, you want to accumulate all of the names and put them into a new Array. Perfect for .reduce().
Note that the acc argument stands for accumulator, so each time you loop through a person, you make your changes to the accumulator and then pass it to the next loop.
Note: I would not recommend solving your problem using .forEach() since forEach will make changes directly to your original Array. Any changes you do, will be applied to people, and you will get a new Array back from forEach. This is why methods such as Array.prototype.map/reduce exist!
const people = [
{ name: "Tom", id: 123} ,
{ name: "chris", id: 1234} ,
{ name: "Simon", id: 111 },
];
const names = people.reduce((acc, person) => {
acc.push(person.name);
return acc;
}, []);

Array of Objects in Javascript on the basis of an element

Lets Suppose I have 1000's of objects. Now I want to store objects with same name in an array So that I'll have multiple arrays having objects with same name. How can this be done in JavaScript?
Data can be like this
var input = [
{ name: 'ABC', age: 12 },
{ name: 'XYZ', age: 13 },
{ name: 'ABC', age: 14 },
{ name: 'XYZ', age: 15 },
];
var output = {};
input.forEach(function(obj) {
var array = output[obj.name];
if (!array) {
array = output[obj.name] = [];
}
array.push(obj)
})
for(name in output) {
console.log('There are ' + output[name].length + ' people named ' + name);
}
In javascript, objects aren't copied into arrays. They exist in memory and when added to a an array the reference to that object is what lives in an array.
In the following code, myObj === arr1[0] === arr2. Which means the following is true:
var myObj = {name:'Dave', age: 55};
var arr1 = [myObj];
var arr2 = [myObj];
arr2[0].age = 44;
console.log(myObj.age);
// prints 44
console.log(arr1[0].age);
// prints 44
So to get what you need, you just need to organize your data into arrays. In javascript, you can filter arrays:
// original data
var data = [
{name: 'ABC', age: 12},
{name: 'XYZ', age: 13},
{name: 'ABC', age: 14},
{name: 'XYZ', age: 15},
{name: 'XYZ', age: 16},
];
// this returns a function to be used in Array.filter to filter for objects with the specified name
function nameFilter(name) {
return function(datum) {
return datum.name === name;
}
}
// filter for each type
var abcPeople = data.filter(nameFilter('ABC'));
var xyzPeople = data.filter(nameFilter('XYZ'));
console.log(data.length);
//5
console.log(abcPeople.length);
//2
console.log(xyzPeople.length);
//3
If you run the above code, you would have 3 arrays and all object in abcPeople would also be in data such that any change to one would be reflected in the other. The same is true for xyzPeople. Just to be clear, filter creates a new array, so data is not modified.
UPDATE: Added example where lists are dynamically determined
// original data
var data = [
{name: 'ABC', age: 12},
{name: 'XYZ', age: 13},
{name: 'ABC', age: 14},
{name: 'XYZ', age: 15},
{name: 'XYZ', age: 16},
];
var sortedData = {};
data.forEach(function(datum){
// initializes an array for any unseen name
if(!sortedData[datum.name]) {
sortedData[datum.name] = [];
}
// add the datum to the list for its name
sortedData[datum.name].push(datum);
});
// all names
console.log(Object.keys(sortedData));
// "ABC", "XYZ"
// items named "ABC"
console.log(sortedData['ABC']);
// [{"name": "ABC","age": 12}, {"name": "ABC","age": 14}]

Categories