Lodash: Swap key with value objects internal attribute - javascript

I am getting below JSON response:
users: {
1: {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
2: {
name: "Alex",
email: "alex#test.com",
id: 2,
place: "FL"
},
3: {
name: "Tony",
email: "tony#test.com",
id: 3,
place: "TX"
}
.
.
.
.
.
.
}
I want to swap the id key with email key from the inner object value as below format.
users: {
"john#test.com": {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
}
I am using below lodash code to make it work and its working fine:
_.keyBy(_.values(data), 'email');
Is there a better way I can handle it with lodash? I am new to lodash and I wanted to understand whether the code can be refactored further.

See _.keyBy() accepts a collection (an array or an object), you can skip the _.values() call:
const users = {"1":{"name":"John","email":"john#test.com","id":1,"place":"NY"},"2":{"name":"Alex","email":"alex#test.com","id":2,"place":"FL"},"3":{"name":"Tony","email":"tony#test.com","id":3,"place":"TX"}};
const result = _.keyBy(users, 'email');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

If you are looking for Vanilla JavaScript solution you can use array#reduce like this:
users = {
1: {
name: "John",
email: "john#test.com",
id: 1,
place: "NY"
},
2: {
name: "Alex",
email: "alex#test.com",
id: 2,
place: "FL"
},
3: {
name: "Tony",
email: "tony#test.com",
id: 3,
place: "TX"
}
}
let newUsers = Object.keys(users).reduce((obj, key) => {
obj[users[key].email] = users[key];
return obj;
}, {});
console.log(newUsers);

Related

Javascript : Concatenate object values in a variable

I'm trying to concatenate values from "seller" Key in a new variables "sellerList" but I'm not achieving to find a good solution.
const data = {
page: {},
product: {
attributes: {
condition: 'used',
offer: {
offer1: {
condition: 'used',
offerID: '1111',
seller: 'Ben',
sellerID: 'abc',
},
offer2: {
condition: 'used',
offerID: '2222',
seller: 'manu',
sellerID: 'def',
},
offer3: {
condition: 'used',
offerID: '3333',
seller: 'Ben',
sellerID: 'abc',
},
},
},
},
};
I found this post which has a similar issue, but it's not working on my side
As we can't use map method on object, I pushed my object into an array like this:
dataArr = [];
dataArr.push(data);
Then I used the following code to concatenate:
const sellersList = Object.keys(digitalData)
.map((o) => o.seller)
.join(';');
console.log('Offer list :' + sellersList);
But this returns an empty string: "Offer list :;"
So my goal is to have a final string like this : "ben;manu;ben"
Does anyone have an idea how to arrange the code fit with my case ?
Thank you for your help and your time.
Based on the data shape that you shared, you can do it like that:
Object.values(data.product.attributes.offer)
.map(offer => offer.seller)
.join(';')
You can do it like this. It does rely on your data having this specific shape with those precise key names - but it's not clear what else you can do as I don't know the details of where your data comes from and what else it might look like. Hope this helps give you a start, anyway!
const data = {
page: {},
product: {
attributes: {
condition: "used",
offer: {
offer1: {
condition: "used",
offerID: "1111",
seller: "Ben",
sellerID: "abc",
},
offer2: {
condition: "used",
offerID: "2222",
seller: "manu",
sellerID: "def",
},
offer3: {
condition: "used",
offerID: "3333",
seller: "Ben",
sellerID: "abc",
},
},
},
},
};
const result = Object.values(data.product.attributes.offer).map(offer => offer.seller).join(";");
console.log(result);

Typescript, how to transform an object to an expeced form

I want to convert or transform an object to the other object, which I want to.
inout object looks like that:
[
{0: {contact: {
1: {
name: abc,
address: street
},
2: {
name: kdf,
address: streedsd
}
}
}
}
{4: {education: {
0: {
uni: ssdabc,
address: street
},
1: {
uni: sdaskdf,
address: streedsd
}
}
}
}
]
what I expeced is:
[
{contact: [
{
name: abc,
address: street
},
{
name: kdf,
address: streedsd
}
]
}
{education: {
[ {
name: abc,
address: street
},
{
name: kdf,
address: streedsd
}
]
}
]
any solutions??? for the best, need a dynamic method, not only for contact.
this input object will be generated dynamically.
You can use Array.map() to iterate over the outer array and Object.values() to get values as array for the contact property.
const data = [{
contact: {
0: {
name: 'abc',
address: 'street'
},
1: {
name: 'kdf',
address: 'streedsd'
}
}
},
{
education: {
0: {
uni: 'ssdabc',
address: 'street'
},
1: {
uni: 'sdaskdf',
address: 'streedsd'
}
}
}
]
const convertedData = data.map(datum => {
Object.keys(datum).forEach(key => {
datum[key] = Object.values(datum[key])
})
return datum;
})
console.log('Converted Data:',convertedData)
console.log('Original Data:', data)
Important
Be aware that this method modifies the original data. If you don't want to modify the original, you can use Array.reduce() instead of Array.map()
You can use Object.values to extract the values of an object into a list.
Here is a code snippet that applies that to each item in your input:
(Various changes have been made to input and outputs in the question, some of them are invalid json but this works for a fixed version of the latest edit)
const input = [{
contact: {
0: {
name: "abc",
address: "street"
},
1: {
name: "kdf",
address: "streedsd"
}
}
}, {
education: {
0: {
uni: "ssdabc",
address: "street"
},
1: {
uni: "sdaskdf",
address: "streedsd"
}
}
}]
const output = input.map(item => Object.entries(item).map(([key, value]) => ({
[key]: Object.values(value)
})))
console.log(output)

javascript find all the object in an array and convert it into an array to array [duplicate]

This question already has an answer here:
Flattening a nested object
(1 answer)
Closed 3 years ago.
I have a list of array with object in it like address and details
Input
var arr = [
{id: 1, name: "abc", address: {street: "some text1", pin: 879888, state: "my-state1"}, details: {section: "A", roll: 12, branch:"CSE"}},
{id: 2, name: "xyz", address: {street: "some text2", pin: 879887, state: "my-state2"}, details: {section: "B", roll: 13, branch:"IT"}}
]
I want to iterate on this array and convert all the inner object so that it will look something like below
Expected Result
var arr = [
{id: 1, name: "abc", street: "some text1", pin: 879888, state: "my-state1", section: "A", roll: 12, branch: "CSE"},
{id: 2, name: "xyz", street: "some text2", pin: 879887, state: "my-state2", section: "B", roll: 13, branch: "IT"}
]
use map and spread operator will simplify.
Alternatively, you can do generic way with out hard coding keys.
var arr = [
{
id: 1,
name: "abc",
address: { street: "some text1", pin: 879888, state: "my-state1" },
details: { section: "A", roll: 12, branch: "CSE" }
},
{
id: 2,
name: "xyz",
address: { street: "some text2", pin: 879887, state: "my-state2" },
details: { section: "B", roll: 13, branch: "IT" }
}
];
const updated = arr.map(item => ({
id: item.id,
name: item.name,
...item.address,
...item.details
}));
const updatedGeneric = arr.map(item => {
let res = {};
Object.entries(item).forEach(([key, value]) => Object.assign(res, typeof value === "object" ? value : { [key]: value }));
return res;
});
console.log(updated);
console.log(updatedGeneric);
In this case, the loop processes the entire array and check if prop is not an object then copy key\value in a new object. If prop is an object just merge this object to new object. then you should return a new object.
var arr = [
{id: 1, name: "abc", address: {street: "some text1", pin: 879888, state: "my-state1"}, details: {section: "A", roll: 12, branch:"CSE"}},
{id: 2, name: "xyz", address: {street: "some text2", pin: 879887, state: "my-state2"}, details: {section: "B", roll: 13, branch:"IT"}}
]
let res = arr.map(row => {
let newRow = {};
for (let key in row) {
if (row.hasOwnProperty(key)) {
if (typeof row[key] !== 'object') {
newRow[key] = row[key];
} else {
newRow = {
...newRow,
...row[key]
}
}
}
}
return newRow;
});
console.info(res);
I think your goal is to flatten the objects in the array. So to achieve this, you could iterate over the object extract the values which are objects, and then spread them into the object. It could look like this:
var arr = [
{ id: 1, name: "abc", address: { street: "some text1", pin: 879888, state: "my-state1" }, details: { section: "A", roll: 12, branch: "CSE" } },
{ id: 2, name: "xyz", address: { street: "some text2", pin: 879887, state: "my-state2" }, details: { section: "B", roll: 13, branch: "IT" } }
]
const newArray = arr.map(obj => {
const newObject = obj
for(let key in newObject) {
if(typeof newObject[key] === "object") {
newObject = {
...newObject,
...newObject[key]
}
delete newObject[key]
}
}
return newObject
})
You can iterate over the array using Array.map, destructure address, details and combine the rest of the properties into a new object using destructuring assignment.
Then merge every object into a single object using Object.assign()
const result = arr.map(({ address, details, ...rest }) =>
Object.assign(rest, address, details));

how to remove an element from a list typescript

Im using Angular 6, I have list and Im exporting it to CSV file using Angular5-csv, I want to remove the last column of the list i.e., the last element of each array in the list. my list looks like
let traceslist = [
{
"name": "abcd",
"email": "abcd#example.com",
"decision": "yes",
"userid": "abcd"
},
{
"name": "phill";
"email": "abcd#example.com";
"decision": "yes";
"userid": "phill";
},
{
"name": "raj";
"email": "raj#example.com";
"decision": "no";
"userid": "raj";
},
{
"name": "john";
"email": "john#example.com";
"decision": "yes";
"userid": "john";
}
]
now, I want to remove the elements userid, so that the column will not be present in my csv file, from the list. I have tried using splice but that was not successful.
It'd be great if anyone of you can help me with this.
Use the .map array method to remove the userid from every item in your array.
traceslist = traceslist.map(item => {
delete item.userid;
return item;
});
By the way, it's not angular related so your title and tag is a little misleading. An array is the same in pure javascript.
You can't use delete to remove an item from an array. This is only used to remove a property from an object.
You should use splice to remove an element from an array:
deleteMsg(removeElement:string) {
const index: number = traceslist.indexOf(removeElement);
if (index !== -1) {
traceslist.splice(index, 1);
}
}
This is a simple javascript problem. Also you need to convert your data to string.
See the example below:
let traceslist = [
{
'name': 'abcd',
'email': 'abcd#example.com',
'decision': 'yes',
'userid': 'abcd'
},
{
'name': 'abcd',
'email': 'abcd#example.com',
'decision': 'yes',
'userid': 'abcd'
}
];
traceslist.forEach( item => delete item.userid );
console.log(traceslist);
We can use .map() method to achieve this
let traceslist = [
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
},
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
},
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
},
{
name: 'abcd',
email: 'abcd#example.com',
decision: 'yes',
userid: 'abcd',
}
]
const result = traceslist.map(o => {
delete o.userid;
return o;
})
console.log(result);
First of all, your JSON format is wrong, semicolon (;) is first and the strings should be in quotes check it below
let obj = [{
name: "abcd",
email: "abcd#example.com",
decision: "yes",
userid: "abcd",
},
{
name: "abcd",
email: "abcd#example.com",
decision: "yes",
userid: "abcd",
},
{
name: "raj",
email: "raj#example.com",
decision: "no",
userid: "raj",
},
{
name: "john",
email: "john#example.com",
decision: "yes",
userid: "john",
}
]
let filtered = obj.map(item => {
delete item.userid;
return item;
});
console.log(filtered);

lodash Groupby based on multiple conditions

i am using angular 4 for one of my projects and i have a situation where i have to group the data based on multiple conditions as explained below.
Raw data
[
{
age: "12",
details: [
{
address: "street1"
}
]
},
{
age: "12",
details: [
{
address: "street2"
}
]
},
{
age: "12",
details: [
{
address: "street1"
}
]
}]
I want to group data based on both age and address field so the result would be something like
{
stree1: [{
age: "12",
details: [
{
address: "street1"
}
]
}, {
age: "12",
details: [
{
address: "street1"
}
]
}
],
street2: [{
age: "12",
details: [
{
address: "street1"
}
]
}]
}
I know we can use lodash to group the data based on single condition like
_.groupBy(data, 'age');
But i am not understanding how to do this based on multiple conditions. I want to group all those objects which has same address and same age. Something like
_.groupBy(data, 'age' && details[0].address);
How to go about this. Please help.
If you are sure that your object structure will be exactly the same always and will have only one object in details then you can directly do Stringify to identify the combo, if your object have several data, then you can create a new object {age: value, street: value} and stringify it to identify the combo. However I will strongly suggest not to use any pipe or anything as deliminator, and joining them to create unique combination of string to find a group. Sometimes that can spoil your value.
Here is what you need:
_(rawData).groupBy(JSON.stringify).filter(arr=>arr.length>1).mapKeys(v=>v[0].details[0].address).value()
Here is an working example:
var rawData = [
{
age: "12",
details: [
{
address: "street1"
}
]
},
{
age: "12",
details: [
{
address: "street2"
}
]
},
{
age: "12",
details: [
{
address: "street1"
}
]
}];
var result = _(rawData)
.groupBy(JSON.stringify)
.filter(arr=>arr.length>1)
.mapKeys(v=>v[0].details[0].address)
.value();
console.log('Expected result: ', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Here is what you do if there can be multiple other things in your object
var rawData = [
{
age: "12",
details: [
{
address: "street1"
}
]
},
{
age: "12",
details: [
{
address: "street2"
}
]
},
{
age: "12",
details: [
{
address: "street1"
}
]
}];
var result = _(rawData)
.groupBy(obj=>JSON.stringify({age: obj.age, address: obj.details[0].address}))
.filter(arr=>arr.length>1)
.mapKeys(v=>v[0].details[0].address)
.value();
console.log('Expected result: ', result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
something like:
const res = _.chain(arr)
.groupBy('age')
.mapValues(ageArr => _.groupBy(ageArr, ageObj => ageObj.details[0].address))
.value();

Categories