How to group by array of objects - javascript

I have an array of objects like the below:
const data = [{label: 'ABC', id: '1', emp:{empLabel: 'Test1', empId: '12'}},
{label: 'ABC', id: '1', emp:{empLabel: 'Test2', empId: '13'}},
{label: 'DEF', id: '2', emp:{empLabel: 'Test11', empId: '14'}},
{label: 'DEF', id: '2', emp:{empLabel: 'Test12', empId: '15'}},
{label: 'PQR', id: '3', emp:{empLabel: 'Test13', empId: '16'}},
{label: 'XYZ', id: '4', emp:{empLabel: 'Test14', empId: '17'}}
]
I am trying to club the emp data if my id is equal.
Expected Output:
[
{label: 'ABC', id: '1', emp:[{empLabel: 'Test1', empId: '12'}, {empLabel: 'Test2', empId: '13'}]},
{label: 'DEF', id: '2', emp:[{empLabel: 'Test11', empId: '14'}, {empLabel: 'Test12', empId: '15'}]},
{label: 'PQR', id: '3', emp:{empLabel: 'Test13', empId: '16'}},
{label: 'XYZ', id: '4', emp:{empLabel: 'Test14', empId: '17'}}
]
I have tried to do this by lodash but am not sure how to proceed after this. Any help would appreciate?
My Approach:
result = _.map(data, eachData => {
return _.chain(_.flatMap(eachData))
})

const _ = require("lodash")
let items = [
{ label: 'ABC', id: '1', emp: { empLabel: 'Test1', empId: '12' } },
{ label: 'ABC', id: '1', emp: { empLabel: 'Test2', empId: '13' } },
{ label: 'DEF', id: '2', emp: { empLabel: 'Test11', empId: '14' } },
{ label: 'DEF', id: '2', emp: { empLabel: 'Test12', empId: '15' } },
{ label: 'PQR', id: '3', emp: { empLabel: 'Test13', empId: '16' } },
{ label: 'XYZ', id: '4', emp: { empLabel: 'Test14', empId: '17' } }
]
var result = _(items)
.groupBy('id')
.map(function(items, label) {
return {
label: label,
emp: _.map(items, 'emp')
};
}).value();
console.log("result -> ", result)

This works, unless you are specifically trying to use lodash:
const result = data.reduce((acc, val) => {
const existingGroup = acc.find((group) => val.id === group.id);
if(!!existingGroup) {
if(existingGroup.emp && Array.isArray(existingGroup.emp)) {
existingGroup.emp = [...existingGroup.emp, val.emp];
} else {
existingGroup.emp = [existingGroup.emp, val.emp]
}
} else {
acc = [...acc, val];
}
return acc;
},[]);
console.log(result);

Try using array.filter(). Do something like
ar = []
let newarr = []
data.map(x => if (ar.indexOf(x)===-1) {newarr.push(x); at.push(x.id))
newArr is now your array.

Related

How to create table with title in React native

I want to create a Table in React native like the below image
TABLE PICTURE🔽🔽🔽🔽🔽
i have two JSON data
tableTitle.json
var tableTitle = [
{ id: '11', last_nom: 'Cars'},
{ id: '12', last_nom: 'Phones'}
];
tableInfo.json
var tableInfo = [
{ id: '1', parent_id: '11', name: 'toyota', model:'camry', year:'2020', country:'japan'},
{ id: '2', parent_id: '11', name: 'huyndai', model:'accent', year:'2018', country:'s.korea'},
{ id: '3', parent_id: '11', name: 'tesla', model:'s30', year:'2022', country:'usa'},
{ id: '4', parent_id: '12', name: 'iphone', model:'14 pro', year:'2020', country:'usa'},
{ id: '5', parent_id: '12', name: 'samsung', model:'ss22', year:'2018', country:'s.korea'},
{ id: '6', parent_id: '12', name: 'pixel', model:'4', year:'2022', country:'usa'},
];
Get table title
useEffect(()=>{
const config = {
method:'get',
url: `http://URL.COM/${id}`,
headers: { }
}
axios(config)
.then(function(response){
let info = response.data
let newArray = info.map((list)=>{
return {id: list.id, name: list.name}
})
setTitle(newArray)
// console.log(newArray)
})
.catch(function (error) {
console.log(error);
})
})

How do I create an array of objects with a nested array based on a similar key?

I have an array that looks something like this
const example = [
{ id: '1', name: 'Person 1', organization: { id: '11', name: 'Organization A' } },
{ id: '2', name: 'Person 2', organization: { id: '12', name: 'Organization A' } },
{ id: '3', name: 'Person 3', organization: { id: '13', name: 'Organization B' } },
];
As you can see, the organization name is something I want to key off of and create a data structure like this:
const output = [
// data.value will be their ID
{
organizationName: 'Organization A',
data: [
{ label: 'Person 1', value: '1' },
{ label: 'Person 2', value: '2' },
],
},
{
organizationName: 'Organization B',
data: [
{ label: 'Person 3', value: '3' },
],
},
]
What I've tried
I know I want to use reduce for something like this, but I feel like I'm off:
const providerOptions = externalPeople.data.reduce((acc, currentValue) => {
const {
organization: { name: organizationName },
} = currentValue;
if (organizationName) {
acc.push({ organization: organizationName, data: [] });
} else {
const { name: externalPersonName, id } = currentValue;
acc[acc.length - 1].data.push({ name: externalPersonName, value: id });
}
return acc;
}, [] as any);
However the output comes out to something like this:
[
{organizationName: 'Organization A', data: []},
{organizationName: 'Organization A', data: []},
{organizationName: 'Organization B', data: []},
];
data doesn't seem to get anything pushed inside the array in this reduce function, and the organization name get duplicated... what am I doing wrong?
Easiest way is to use an Map/Set/or object to keep track of orgs you create. This way you are not searching in the array to see if the organization was found already. After you are done, you can create the array you want from the object.
const externalPeople = {
data : [
{ id: '1', name: 'Person 1', organization: { id: '11', name: 'Organization A' } },
{ id: '2', name: 'Person 2', organization: { id: '12', name: 'Organization A' } },
{ id: '3', name: 'Person 3', organization: { id: '13', name: 'Organization B' } },
],
};
const providerOptions = Object.values(externalPeople.data.reduce((acc, currentValue) => {
const {
organization: { name: organizationName },
name: externalPersonName,
id
} = currentValue;
// Is the org new? Yes, create an entry for it
if (!acc[organizationName]) {
acc[organizationName] = { organization: organizationName, data: [] };
}
// push the person to the organization
acc[organizationName].data.push({ name: externalPersonName, value: id });
return acc;
}, {}));
console.log(providerOptions)
Here is another solution
const example = [
{ id: '1', name: 'Person 1', organization: { id: '11', name: 'Organization A' } },
{ id: '2', name: 'Person 2', organization: { id: '12', name: 'Organization A' } },
{ id: '3', name: 'Person 3', organization: { id: '13', name: 'Organization B' } },
];
const result = example.reduce((res, entry) => {
const recordIndex = res.findIndex(rec => rec.organizationName === entry.organization.name);
if(recordIndex >= 0) {
res[recordIndex].data.push({ label: entry.name, value: entry.id});
} else {
const record = {
organizationName: entry.organization.name,
data: [{ label: entry.name, value: entry.id }]
};
res.push(record);
}
return res;
}, []);
console.log(result);
You are not checking if the value is already present in your accumulation acc
You can check it with a simple find in the if statement since it's an array
const providerOptions = externalPeople.data.reduce((acc, currentValue) => {
const {
organization: { name: organizationName },
} = currentValue;
//Check if organization is not present already
if (!acc.find(a => a.organization === organizationName)) {
//Add also the data of the element your are processing
acc.push({ organization: organizationName, data: [{label: currentValue.name, value: currentValue.id}] });
} else {
const { name: externalPersonName, id } = currentValue;
acc[acc.length - 1].data.push({ label: externalPersonName, value: id });
}
return acc;
}, [] as any);
I also added the data of the first element of the group you create when adding the organization.
The result should be as your expected output:
[
{
organization: 'Organization A',
data: [
{ label: 'Person 1', value: '1' },
{ label: 'Person 2', value: '2' }
]
},
{
organization: 'Organization B',
data: [
{ label: 'Person 3', value: '3' }
]
}
]
Hope it helps!
Compare this solution (using Lodash) with other solutions. Which one emphasises your intentions at most? This is why we use Lodash in our company - to maintain code as declarative as we can, because code readability, with minimum cognitive overload, is most important goal during coding.
const persons = [
{ id: '1', name: 'Person 1', organization: { id: '11', name: 'Organization A' } },
{ id: '2', name: 'Person 2', organization: { id: '12', name: 'Organization A' } },
{ id: '3', name: 'Person 3', organization: { id: '13', name: 'Organization B' } },
];
const personsByOrganizations = _.groupBy(persons, 'organization.name')
const output = _.map(personsByOrganizations, (persons, organizationName) => ({
organizationName,
data: _.map(persons, ({ name, id }) => ({
label: name,
value: id
}))
}))
Something like that with using a Set?
result = [...new Set(example.map(d => d.organization.name))].map(label => {
return {
organizationName: label,
data: example.filter(d => d.organization.name === label).map(d => {
return {label: d.name, value: d.id}
})
}
})
`

Transform object with nested array into a big object

I need some help to prepare my object properly to update my database
What I get from the API:
{
currency: 'USD',
product_id: '1',
user_id: '123',
service_id: '999',
tech: 'javaScript',
price: '50',
details: [
{ detail_type: 'hours_service', value: '5' },
{ detail_type: 'workers', value: '2' },
{ detail_type: 'machines', value: '2' },
{ detail_type: 'instances', value: '1' },
{ detail_type: 'difficulty', value: '2' },
],
date_start: '2021-06-20',
date_stop: '2021-06-21',
}
What I need to update my DB:
{
currency: 'USD',
product_id: '1',
user_id: '123',
service_id: '999',
tech: 'javaScript',
price: '50',
hours_service: '5',
workers: '2',
machines: '2',
instances: '1',
difficulty: '2',
date_start: '2021-06-20',
date_stop: '2021-06-21',
}
my attempt:
const api_data = {
currency: 'USD',
product_id: '1',
user_id: '123',
service_id: '999',
tech: 'javaScript',
price: '50',
details: [
{ detail_type: 'hours_service', value: '5' },
{ detail_type: 'workers', value: '2' },
{ detail_type: 'machines', value: '2' },
{ detail_type: 'instances', value: '1' },
{ detail_type: 'difficulty', value: '2' },
],
date_start: '2021-06-20',
date_stop: '2021-06-21',
}
for (let item of api_data.details) {
var arr = item
var result = {};
for (var i = 0, len = arr.length; i < len; i++) {
result[arr[i].key] = arr[i].value;
}
console.log(result);
}
The attempt I've made gives me a lot of empty objects...
How can I make the first object detail array transform in key:value pair and make it one big object with all data?
thanks in advance,
Kind regards
You can use reduce to acheive this
const apiData = {
currency: 'USD',
product_id: '1',
user_id: '123',
service_id: '999',
tech: 'javaScript',
price: '50',
details: [
{ detail_type: 'hours_service', value: '5' },
{ detail_type: 'workers', value: '2' },
{ detail_type: 'machines', value: '2' },
{ detail_type: 'instances', value: '1' },
{ detail_type: 'difficulty', value: '2' },
],
date_start: '2021-06-20',
date_stop: '2021-06-21',
};
const {details,...rest} = apiData;
const transformedObj = details.reduce((result,item)=>({...result,[item.detail_type]:item.value}),{});
const result = {...rest,...transformedObj};
console.log(result);

Filter two array of objects and get a resultant array

I'm trying to check for condition where carId in one array is equal to id of another array.
Below is the code snippet.
const arr1 = [{
id: '1',
type: 'car',
name: 'BMW',
},
{
id: '2',
type: 'car',
name: 'Audi',
},
{
id: '3',
type: 'car',
name: 'Benz',
}
];
const arr2 = [{
carId: '1'
}, {
carId: '3'
}];
const result = arr2.map(val => arr2.find(val.carId === id))
console.log(result)
The result that I'm expecting is
[{
id: '1',
type: 'car',
name: 'BMW',
},
{
id: '3',
type: 'car',
name: 'Benz',
}
];
Could anyone please help?
While you should use .filter() on arr1, and pass a callback to .find(), I'd probably first convert arr2 to a simple list of IDs and use .includes() instead.
const arr1 = [{
id: '1',
type: 'car',
name: 'BMW',
},
{
id: '2',
type: 'car',
name: 'Audi',
},
{
id: '3',
type: 'car',
name: 'Benz',
}
];
const arr2 = [{
carId: '1'
}, {
carId: '3'
}];
const ids = arr2.map(o => o.carId);
const result = arr1.filter(val => ids.includes(val.id))
console.log(result)
or better yet, convert arr2 to a Set.
const arr1 = [{
id: '1',
type: 'car',
name: 'BMW',
},
{
id: '2',
type: 'car',
name: 'Audi',
},
{
id: '3',
type: 'car',
name: 'Benz',
}
];
const arr2 = [{
carId: '1'
}, {
carId: '3'
}];
const ids = arr2.map(o => o.carId);
const idSet = new Set(ids);
const result = arr1.filter(val => idSet.has(val.id))
console.log(result)
const arr1 = [{
id: '1',
type: 'car',
name: 'BMW',
},
{
id: '2',
type: 'car',
name: 'Audi',
},
{
id: '3',
type: 'car',
name: 'Benz',
}
];
const arr2 = [{
carId: '1'
}, {
carId: '3'
}];
const result = arr1.filter(a1val => arr2.find(a2val => a2val.carId === a1val.id) !== undefined);
console.log(result);
This might work
const result = arr2.map(val => arr1.find(item => item.id === val.carId))

Javascript - Best/fastest way to add element to query result with fixed value

I have a node.js mysql query:
connection.query("SELECT id AS id, name AS label, status AS status from table;", function(err, rows) {
...
});
The result I'm getting back locks like this:
console.log(getBody)
[ { id: '1',
label: 'Name 01',
status: 'ACTIVE' },
{ id: '2',
label: 'Name 02',
status: 'INACTIVE' },
{ id: '3',
label: 'Name 03',
status: 'ACTIVE' },
{ id: '4',
label: 'Name 04',
status: 'ACTIVE' }];
To further cosume the result ... I need an additional paremeter 'type' with with a fixed value in the array. So result should look like this:
[ { id: '1',
label: 'Name 01',
status: 'ACTIVE',
type: 'ABC' },
{ id: '2',
label: 'Name 02',
status: 'INACTIVE',
type: 'ABC' },
{ id: '3',
label: 'Name 03',
status: 'ACTIVE',
type: 'ABC' },
{ id: '4',
label: 'Name 04',
status: 'ACTIVE',
type: 'ABC' }];
What's the fastest/best way to do this? Looping over the array? How should it look like?
Use the map method:
const newArray = array1.map(element => element = {...element, ...{type: 'ABC'}});
console.log(array1); // array1 won't be changed
console.log(newArray);
Or forEach, this will modify your array:
array1.forEach(element => element.type = 'ABC');
console.log(array1);
var arr = [
{id: '1',label: 'Name 01',status: 'ACTIVE'},
{id: '2',label: 'Name 02',status: 'INACTIVE'},
{id: '3',label: 'Name 03',status: 'ACTIVE'},
{id: '4',label: 'Name 04',status: 'ACTIVE'}];
var new_arr = arr.map(function(el) {
var o = Object.assign({}, el);
o. type = 'ABC';
return o;
})
console.log(arr);
console.log(new_arr);

Categories