How to replace a key inside a nested object - javascript

I have this list
{
'0': { id: 'id3', name: 'Capitan America', job: 'superHero' },
'1': { id: 'id4', name: 'Spider-man', job: 'Pro footballer' }
}
And i want to change my keys to the id value like this:
{
id3 : { id: 'id3', name: 'Capitan America', job: 'superHero' },
id4 : { id: 'id4', name: 'Spider-man', job: 'Pro footballer' }
}
this is what i have tried in my code where in my fetch items i transform an array of objects into an object of objects and when i transform into one object of object my keys stayed like the index of the array:
fetchItems() {
const objectified = Object.assign({},this.list)
return objectified;
}

When you use Object.assign to assign an array to an object, indices of the array will become properties of the assigned object. The best way to construct your desired object is to build it manually.
Modify your fetchItems as below:
function fetchItems() {
const result = {};
for (const item of list)
result[item.id] = item;
return result;
}

Here is one way to do what you are asking by stepping over each property, building a new object.
var objA = {
'0': { id: 'id3', name: 'Capitan America', job: 'superHero' },
'1': { id: 'id4', name: 'Spider-man', job: 'Pro footballer' }
};
function transform(obj) {
var newObj = {};
for(p in obj) { newObj[obj[p].id] = obj[p]; }
return newObj;
}
var objB = transform(objA);
console.log(objB);

You could use Object.entries and iterate through the key-value pairs with .reduce
const data = {
0: { id: "id3", name: "Capitan America", job: "superHero" },
1: { id: "id4", name: "Spider-man", job: "Pro footballer" },
}
const res = Object.entries(data).reduce(
(acc, el) => ({ ...acc, [el[1].id]: el[1] }),
{}
)
console.log(res)

Map the array to pairs of [id, object], and then convert to an object using Object.fromEntries():
const arr = [
{ id: 'id3', name: 'Capitan America', job: 'superHero' },
{ id: 'id4', name: 'Spider-man', job: 'Pro footballer' }
]
const result = Object.fromEntries(arr.map(o => [o.id, o]))
console.log(result)

Related

mapping two arrays of equivalent length by object attributes javascript [duplicate]

This question already has answers here:
Merge two array of objects based on a key
(23 answers)
Closed 1 year ago.
I have two arrays:
Array 1:
[
{
name: 'Bob',
traits: {
id: 1
}
}, {
name: 'Karl',
traits: {
id: 2
}
}, {
name: 'Joseph',
traits: {
id: 3
}
}
]
Array 2:
[
{
name: 'Karl',
user_id: 2,
dog: 'Rottweiler'
}, {
name: 'Joseph',
user_id: 3,
dog: 'Poodle'
}, {
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
]
Desired outcome:
I want to be able to merge the second array into the first array by finding what element user_id matches with id and then adding the object to array.
For example:
array 1 obj
{
name: 'Bob',
traits: {
id: 1
}
}
Since the id matches with array 2 obj user_id:
{
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
Final outcome will be:
{
name: 'Bob',
traits: {
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
}
arr2.forEach((obj) => {
const idx = arr1.findIndex((o) => o.traits.id === obj.user_id);
if (idx !== -1) {
arr1[idx] = { ...arr1[idx], traits: { ...obj } }
}
})
console.log(arr1[0]) // { name: 'Bob', traits: { name: 'Bob', user_id: 1, dog: 'Puppy' } }
Turn the second array into a map keyed by user_id, and then iterate the first array. Find the corresponding object in the map, and spread the matching object value into the traits property:
let arr1 = [{name: 'Bob',traits: {id: 1}},{name: 'Karl',traits: {id: 2}},{name: 'Joseph',traits: {id: 3}}];
let arr2 = [{name: 'Karl', user_id: 2,dog: 'Rottweiler'},{name: 'Joseph', user_id: 3,dog: 'Poodle'},{name: 'Bob',user_id: 1,dog: 'Puppy'}];
let map = new Map(arr2.map(item => [item.user_id, item]));
let result = arr1.map(item => {
let traits = map.get(item.traits.id);
return traits ? { ...item, traits} : item;
});
console.log(result);
As lookup in a map has an amortised time complexity of O(1), this is more efficient than finding the key in the array on every iteration (like with calling find).
You can easily achieve this result using map and find. Just map over the first array and find the element with obj.traits.id in the arr2. then return the desired result.
const arr1 = [
{
name: "Bob",
traits: {
id: 1,
},
},
{
name: "Karl",
traits: {
id: 2,
},
},
{
name: "Joseph",
traits: {
id: 3,
},
},
];
const arr2 = [
{
name: "Karl",
user_id: 2,
dog: "Rottweiler",
},
{
name: "Joseph",
user_id: 3,
dog: "Poodle",
},
{
name: "Bob",
user_id: 1,
dog: "Puppy",
},
];
const result = arr1.map((obj) => {
const { name, traits } = obj;
const isExist = arr2.find((o) => o.user_id === traits.id);
if (isExist) {
return { name, traits: { ...isExist } };
}
return obj;
});
console.log(result);
let a = [
{
name: 'Bob',
traits: {
id: 1
}
}, {
name: 'Karl',
traits: {
id: 2
}
}, {
name: 'Joseph',
traits: {
id: 3
}
}
];
let b = [
{
name: 'Karl',
user_id: 2,
dog: 'Rottweiler'
}, {
name: 'Joseph',
user_id: 3,
dog: 'Poodle'
}, {
name: 'Bob',
user_id: 1,
dog: 'Puppy'
}
];
a.map(aobj =>{
let sameIdObj = b.find( bobj => bobj.user_id === aobj.traits.id )
sameIdObj && (aobj.traits = sameIdObj)
})
console.log(a);

How to create sorted object by date

I'am trying to solve an issue that requires the sort of an array of objects containing information. For example, transform this:
[
{
name: 'test1',
date: '2019-02-18T08:33:01.000Z',
},
{
name: 'test2',
date: '2019-02-19T08:33:01.000Z',
},
{
name: 'test3',
date: '2019-02-19T08:33:01.000Z',
},
]
To this:
{
'2019-02-18':{
name: 'test1'
},
'2019-02-19':[
{
name: 'test2',
},
{
name: 'test3',
}
]
}
How can i achieve this?
Assuming you want an array of objects for every grouped date. One alternative is to use Array.reduce() in conjunction with String.match()
const input = [
{name: 'test1', date: '2019-02-18T08:33:01.000Z'},
{name: 'test2', date: '2019-02-19T08:33:01.000Z'},
{name: 'test3', date: '2019-02-19T08:33:01.000Z'}
];
let res = input.reduce((acc, {name, date}) =>
{
let [m, d] = date.match(/(.+)T/);
acc[d] = [...(acc[d] || []), {name}];
return acc;
}, {});
console.log(res);
This is more a group by problem than a sort. Object keys are unsorted, also.
function groupByDate(data) {
let result = {};
data.forEach((el) => {
let datePart = el.date.split("T")[0];
let value = result[datePart]
if(value) {
result[datePart].push({name: el.name})
} else {
result[datePart] = [{name: el.name}]
}
});
return result;
}
var dates = [
{
name: 'test1',
date: '2019-02-18T08:33:01.000Z',
},
{
name: 'test2',
date: '2019-02-19T08:33:01.000Z',
},
{
name: 'test3',
date: '2019-02-19T08:33:01.000Z',
},
];
console.log(groupByDate(dates));

Array.filter() to remove duplicate Ojects

I would like to fuse Array.filter() function to remove duplicate objects
I am able to achieve in the case of string or integer arrays. But I am not able to achieve the same with array of objects as in the second case of names
const names = ['John', 'Paul', 'George', 'Ringo', 'John'];
let x = names => names.filter((v, i, arr) => arr.indexOf(v) === i);
console.log(x(names)); //[ 'John', 'Paul', 'George', 'Ringo' ]
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" } ];
// returns the same original array
Could you please help?
Using Array#reduce() and a Map accumulator then spread the values() of the Map into array
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" } ];
const unique = [... names.reduce((a,c)=>(a.set(c.name,c)),new Map).values()]
console.log(unique)
Use Array.reduce and Object.values
Iterate over the array and create an object with key as name and value as object from array. In case of objects with same name, the value will be overwritten in resultant object. Finally use Object.values to collect all the unique objects.
const names = [{ name: "John" },{ name: "Paul" },{ name: "George" },{ name: "Ringo" },{ name: "John" } ];
let result = Object.values(names.reduce((a,c) => Object.assign(a, {[c.name]:c}),{}));
console.log(result);
For tweaking - Plunker
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" }
];
/* unique => Filter: Remove all duplicate items from an array. Works with plain objects as well, since we stringify each array item.
* #type public Function
* #name unique
* #return Function( item )
* #notes
*/
const unique = () => {
const seen = {};
return item => {
const json = JSON.stringify( item );
return seen.hasOwnProperty( json )
? false
: ( seen[ json ] = true );
};
};
const result = names.filter( unique() );
console.log( result );
You could use lodash's _uniqBy for this:
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" } ];
const result = _uniqBy(names, 'name');
This can be done with the help of Sets as well
var names = [{ name: "John" },{ name: "Paul" },{ name: "George" },{ name: "Ringo" },{ name: "John" } ];
var result = Array.from(
names.reduce((s, d) => s.add(d.name), new Set)
, d => ({ name: d })
)
console.log(result)
Keith had a great suggestion to use findIndex with filter instead of indexOf. Object literals are always unique references, so we cannot compare them. We can however compare the name keys between the objects. We can do this with the aforementioned functions.
const names = [
{ name: "John" },
{ name: "Paul" },
{ name: "George" },
{ name: "Ringo" },
{ name: "John" }
];
console.log(names.filter(({name1}, i, a) => {
return i == a.findIndex(({name2}) => {
return name1 == name2;
});
});
const names = ['John', 'Paul', 'George', 'Ringo', 'John'];
function removeDups(names) {
let unique = {};
names.forEach(function(i) {
if(!unique[i]) {
unique[i] = true;
}
});
return Object.keys(unique);
}
removeDups(names); //'John', 'Paul', 'George', 'Ringo'

How do I use the reduce method in loDash? Or Javascript Take a Array of Objects and Make one Object

I have a Array of Objects:
` tempArray = [
{ name: 'Lion-O' },
{ gender: 'Male' },
{ weapon: 'Sword of Omens' },
{ status: 'Lord of the Thundercats' },
]
`
Object I want to Transform into:
`{
name: 'Lion-O',
gender: 'Male,',
weapon: 'Sword of Omens',
status: 'Lord of the Thundercats'
}`
I tried to use reduce in LoDash;
const tempObj = _.reduce(tempArray, (r, v, k) => {
return r
})
console.log(tempObj);
//=> { name: 'Lion-O' }
I'm not sure how I should iterate over the Array? Looked at Doc's their example shows Adding or Pushing onto a Array .. I just want a Object.. I know it can be done. If their is a better way I'm open to that as well
Thanks in advance.
Shorter equivalent solution :
const tempArray = [
{ name: 'Lion-O' },
{ gender: 'Male' },
{ weapon: 'Sword of Omens' },
{ status: 'Lord of the Thundercats' },
];
const newObj = Object.assign({}, ...tempArray);
console.log(newObj);
// Object {name: "Lion-O", gender: "Male", weapon: "Sword of Omens", status: "Lord of the Thundercats"}
tempArray = [
{ name: 'Lion-O' },
{ gender: 'Male' },
{ weapon: 'Sword of Omens' },
{ status: 'Lord of the Thundercats' },
]
var newObject = {};
for (var index in tempArray) {
thisObject = tempArray[index];
for (var key in thisObject) {
newObject[key] = thisObject[key];
}
}
console.log(newObject);

Return duplicate objects and its position in javascript

I have a big set of objects in javascript array. I Need to find all duplicate object having same name.
e.g.
values = [
{ name: 'Name1', index:0 },
{ name: 'Name2', index:1 },
{ name: 'Name1', index:2 },
{ name: 'Name2', index:3 },
{ name: 'Name1', index:4 },
]
What I expect is a array having two objects
values = [
{ name: 'Name1', index:2 },
{ name: 'Name2', index:3 },
{ name: 'Name1', index:4 }
]
because these are the duplicates.
New additions to ES6 are really interesting here, such as the Set class. This code does not modify your initial object, but it's simple to adapt.
function unique(values) {
const knownNames = new Set();
const result = [];
for (const value of values) {
if (!knownNames.has(value.name)) {
knownNames.add(value.name);
result.push(value);
}
}
return result;
}
This probably isn't the most efficient way and you should probably use the Set if you don't need to worry about IE9
values = [
{ name: 'Name1', index:0 },
{ name: 'Name2', index:1 },
{ name: 'Name1', index:2 },
{ name: 'Name2', index:3 },
{ name: 'Name1', index:4 },
]
// check an array for an object with a matching name property
// `some` will return early so you don't need to process the whole array
// if a match is found
const contains = (name, arr) => arr.some(item => item.name === name)
// reduce the array to keep the value contained
const output = values.reduce((acc, value) => {
if (!contains(value.name, acc)) {
return acc.concat(value)
}
return acc
}, [])
console.log('first unique', output)

Categories

Resources