How do I do this in Lodash? - javascript

I have a array like structure from database results
var arr = [{name: 'a', age: 23}, {name: 'b', age: 24}, {name: 'c', age: 35}]
I want to create a new object with values as key and value like below:
var new_arra = {a: 23, b: 24, c: 35}
How can I do this in lodash?
I tried the below method:
var result = _.forEach(results, function(index) {
var result = _.map(index, function(value, prop) {
return {prop: prop, value: value};
});
});

Using ES5 - iterate with Array#reduce with initial value of an empty object. On each iteration set the name as key, and the age as value.
var arr = [{name: 'a', age: 23}, {name: 'b', age: 24}, {name: 'c', age: 35}];
var result = arr.reduce(function(obj, o) {
obj[o.name] = o.age;
return obj;
}, {});
console.log(result);
Using ES6 - Iterate with Array#map get the values using destructuring, and set using computed property names. Combine all to a single object by using Object#assign with the spread syntax:
const arr = [{name: 'a', age: 23}, {name: 'b', age: 24}, {name: 'c', age: 35}];
const result = Object.assign({}, ...arr.map(({ name, age }) => ({ [name]: age })));
console.log(result);

You can do it with pure JS this way:
var arr = [{
name: 'a',
age: 23
}, {
name: 'b',
age: 24
}, {
name: 'c',
age: 35
}]
var result = {};
arr.forEach(function(item) {
result[item.name] = item.age
});
console.log(result);
Another way with reduce:
var arr = [{
name: 'a',
age: 23
}, {
name: 'b',
age: 24
}, {
name: 'c',
age: 35
}];
var result = arr.reduce(function(store, item) {
store[item.name] = item.age;
return store;
}, {});
console.log(result);

you need these two line only
let newData = {};
arr.map((item)=>newData[item.name]=item.age);
console.log(newData);
or you can also do it using lodash
let newData = {};
_.map(arr,(item)=>newData[item.name]=item.age);

That's simple.
All you need to do is loop through each data and insert it into a new empty object.
Ex.
let new_arra = {};
_.each(arr, a => {
new_arra[a.name] = a.age
});

Related

Convert object to string while join array in javascript

I want to convert array to string & if array contain object then need to convert in string.
array = [
'a',
'b',
{ name: 'John doe', age: 25 }
]
My code:
const convertedArray = array.join(' ');
Output like below:
a b "{"name":"john", "age":22, "class":"mca"}"
You can use array reduce function. Inside the reduce callback check if the current object which is under iteration is an object or not. If it is an object then use JSON.stringify and concat with the accumulator.
const array = [
'a',
'b',
{
name: 'John doe',
age: 25
}
];
const val = array.reduce((acc, curr) => {
if (typeof curr === 'object') {
acc += JSON.stringify(curr);
} else {
acc += `${curr} `
}
return acc;
}, '');
console.log(val)
Using JSON.stringify on the entire array will have starting and ending [ and ] respectively, which is not what you are looking
const array = [
'a',
'b',
{
name: 'John doe',
age: 25
}
];
console.log(JSON.stringify(array))
Simple ! Try following :
var arr = [
'a',
'b',
{ name: 'John doe', age: 25 }
]
var newArr = arr.map(i => typeof i === "object" ? JSON.stringify(i) : i)
console.log(newArr)
output :
['a', 'b', '{"name":"John doe","age":25}']

Take an object from an array of objects based on the max value on one of its properties

Let's say I got an array of object like this
const arr = [
{name: 'John', age: 15},
{name: 'Max', age: 17},
{name: 'Tom', age: 11},
]
How can I take just the object containing Max, 17?
This would be the result
b = [{ name: Max, age: 17 }]
or better
c = { name: Max, age: 17 }
Reduce the array to the object with highest age:
const arr = [{"name":"John","age":15},{"name":"Max","age":17},{"name":"Tom","age":11}]
const result = arr.reduce((acc, o) => !acc || o.age > acc.age ? o : acc, null)
console.log(result)
I'm using null as the default value for the Array.reduce() to prevent an error if the array is empty. However, you can check for an empty array beforehand as well:
const findMaxAge = arr => arr.length
? arr.reduce((acc, o) => o.age > acc.age ? o : acc)
: null
const arr = [{"name":"John","age":15},{"name":"Max","age":17},{"name":"Tom","age":11}]
console.log(findMaxAge(arr))
console.log(findMaxAge([]))
You can sort by age first, then the object with the highest age value will be at the start of the list:
const a = [
{name: "John", age: 15},
{name: "Max", age: 17},
{name: "Tom", age: 11},
]
const sortedByAge = a.sort((a,b) => b.age - a.age);
const highestAge = sortedByAge[0];
console.log(highestAge);
hope this code helping you
const a = [{name: 'John', age: 15},
{name: 'Max', age: 17},
{name: 'Tom', age: 11},];
const result = a.reduce((p, c) => p.age > c.age ? p : c);
console.log(result);
Using the Array.prototype.reduce() is a clean way.
this function iterates through the array one by one, at each step adding the current array value to the result from the previous step. in our case will compare the previous largest element to the current. the return value will be the object containing the largest value for the age key.
const arr = [
{name: 'John', age: 15},
{name: 'Max', age: 17},
{name: 'Tom', age: 11},
]
const largest = arr.reduce((prev, current) => (prev.age > current.age) ? prev : current)
console.log(largest);

How can you merge objects in array of objects?

I'm looking for the best solution to merge all objects in one array
const arrayOfObjects = [
{name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
];
I want to achieve: {name: ['Fred', 'Anne'], surname: ['Example', 'Shultz']}
What's the best option for that (es6)? Maybe I can do something like that using lodash? Which helpers should I use?
You could reduce the array by iterating the entries and collecting the values, depending of the keys.
const
array = [{ name: 'Fred', surname: 'Shultz' }, { name: 'Anne', surname: 'Example' }],
result = array.reduce((r, o) => {
Object.entries(o).forEach(([k, v]) => (r[k] = r[k] || []).push(v));
return r;
}, Object.create(null));
console.log(result);
You could do it like this:
const arrayOfObjects = [
{name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
];
const result = {};
arrayOfObjects.forEach(item => {
Object.keys(item).forEach(key => {
if (!result[key]) {
result[key] = [];
}
result[key].push(item[key]);
});
});
console.log(result);
easy with lodash:
grouped = _.mapValues(arrayOfObjects[0],
(val, key) => _.map(arrayOfObjects, key))
pure es6
let grouped = {};
for (let obj of arrayOfObjects)
for (let [key, val] of Object.entries(obj))
grouped[key] = (grouped[key] || []).concat(val)
if the keys differ from item to item, you could use something like this to collect them all:
grouped = _(arrayOfObjects)
.flatMap(_.entries)
.groupBy(0)
.mapValues(x => _.map(x, 1))
.value()
You can use lodash's mergeWith like so:
const result = _.mergeWith({}, ...arrayOfObjects, (value, objValue) =>
(value || []).concat(objValue)
);
Example:
const arrayOfObjects = [
{name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
];
const result = _.mergeWith({}, ...arrayOfObjects, (value, objValue) =>
(value || []).concat(objValue)
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
Short way with array reduce:
const arrayOfObjects = [
{name: "name1", surname: "surname1"}, {name: 'Anne', surname: 'Example'}, {name: 'name3', surname: 'Example3'}
];
/*
{name: ['Fred', 'Anne'], surname: ['Example', 'Shultz']}
*/
var result = arrayOfObjects.reduce((obj,current)=>{
(obj['name'] = obj['name']||[]).push(current.name);
(obj['surname'] = obj['surname']||[]).push(current.surname);
return obj;
},{});
console.log(result);
Don't make it any more complicated than it needs to be:
const arrayOfObjects = [
{name: 'Fred', surname: 'Shultz'},
{name: 'Anne', surname: 'Example'}
];
const result = {name:[], surname:[]};
for (const obj of arrayOfObjects)
for (const prop in result)
result[prop].push(obj[prop]);
I will assume that you statically know the property names that your result should have - one can't really do it dynamically anyway as that wouldn't work properly for an empty input array.
Here is a lodash approach
_(input).flatMap(_.entries).groupBy(0).mapValues(v => _.map(v, 1)).value()
var input = [
{name: 'Fred', surname: 'Shultz'}, {name: 'Anne', surname: 'Example'}
];
var res = _(input).flatMap(_.entries).groupBy(0).mapValues(v => _.map(v, 1)).value()
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
This will take care if the objects doesn't have exactly same key sets
If the arrayOfObjects is set on these 2 props then it is as simple as:
const data = [{ name: 'Fred', surname: 'Shultz' }, { name: 'Anne', surname: 'Example' }]
const r = data.reduce((r,c) =>
(r.name.push(c.name), r.surname.push(c.surname),r), {name:[], surname:[]})
console.log(r)
One reduce with an accumulator of {name:[], surname:[]} to be filled.
If you need to be more generic and work for any set of objects:
const data = [{
name: 'Fred',
surname: 'Shultz'
},{
name: 'Anne',
surname: 'Example'
},{
name: 'John',
position: 'Dev' // <--- Notice different prop
}]
const result = data.reduce((r,c) =>
(Object.keys(c).map(k => r[k] = [...r[k] || [], c[k]]), r), {})
console.log(result)
Again is just a reduce with Object.keys to do the job.
Note both approaches utilize ES6 arrow functions, array destricturing and (for the 2nd one) combining multiple operations via enclosing them in parentheses (op1,op2)
This is one abroach of implementation details, written in fairly easy to understand and readable manner.
https://codesandbox.io/s/r7x16j950n
const arrayOfObjects = [
{ name: "Fred", surname: "Shultz" },
{ name: "Anne", surname: "Example" }
];
let obj = {};
arrayOfObjects.forEach(row => {
Object.keys(row).forEach(key => {
obj[key] = !obj[key]
? [row[key]]
: [...obj[key], row[key]];
});
});
console.log(obj);
The following should work - uses a few ES6 helpers, but the key is Array#reduce which is in ES5.
const result = arrayOfObjects.reduce((acc, obj) => {
for (let key in obj) {
if (key in acc) {
acc[key].push(obj[key]);
}
else {
acc[key] = [obj[key]];
}
}
return acc;
}, {});
Without any library
const mergeObjectInArray=(input)=>{
const myObj={};
Object.keys(input[0]).forEach(key=>myObj[key]=input.map(inp=>inp[key]));
return myObj;
}
with pure javascript
var myInput = [{ a: 1, b: 2, c: 3 }, { a: 2, b: 4, c: 6 }, { a: 7, b: 8, c: 9 }];
var myArray = [];
var myObject = {};
function isArray(a){
return Object.prototype.toString.call(a) === '[object Array]' ;
}
for (var i = 0; i < myInput.length; i++) {
for (var key in myInput[i]) {
if (myInput[i].hasOwnProperty(key)) {
if (myArray.indexOf(key) === -1) {
myArray.push(key);
myObject[key] = myInput[i][key];
} else {
if (myObject.hasOwnProperty(key)) {
newary = [];
if (isArray(myObject[key])) {
for (var i = 0; i < myObject[key].length; i++) {
newary.push(myObject[key][i]);
}
} else {
newary.push(myObject[key]);
}
newary.push(myInput[i][key]);
myObject[key] = newary;
}
}
}
}
}
console.log(myObject);

Remove duplicates from array, convert to array of objects and add duplicate count property

I have an array of strings:
var array = ['bob', 'charlie', 'bob', 'bob'];
that I want to remove duplicates from, and then I'd like to convert it to an array of objects whilst adding a duplicate count property.
This is what I want to achieve:
var filteredData = [{ name: 'bob', count: 3}, { name: 'charlie', count: 1}];
How can I do that?
Ecmascript5 solution using Array.prototype.reduce() function:
var arr = ['bob', 'charlie', 'bob', 'bob'],
counts = arr.reduce(function(r,s){
(!r[s])? r[s] = {name: s, count: 1} : r[s]['count']+=1;
return r;
}, {}),
result = Object.keys(counts).map(function(k){ return counts[k]; });
console.log(result);
Ecmascript6 version (with Object.values() function):
var arr = ['bob', 'charlie', 'bob', 'bob'],
result = Object.values(arr.reduce((r,s) => {
(!r[s])? r[s] = {name: s, count: 1} : r[s]['count']+=1;
return r;
}, {}));
console.log(result);
Using Map with Array#reduce:
const array = ['bob', 'charlie', 'bob', 'bob'];
const result = [...array.reduce((map, name) => {
const current = map.get(name) || { name, count: 0 };
current.count++;
return map.set(name, current);
}, new Map()).values()];
console.log(result);
Here is some straightforward usage of Array.prototype.reduce:
const data = ['bob', 'charlie', 'bob', 'bob']
const result = data.reduce(function(prev, curr) {
const index = prev.findIndex(el => el.name === curr)
if (index !== -1) {
prev[index].count += 1
} else {
prev.push({ name: curr, count: 1 })
}
return prev
}, [])
console.log(result)

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