how to reorganize an array of object using lodash - javascript

Is there a way I can make A to B using lodash? Appreciated.
A - Original array looks like below.
[
{
"customerId": 5458122321,
"customerName": "C1"
},
{
"customerId": 5461321801,
"customerName": "C1"
},
{
"customerId": 5434315807,
"customerName": "C2"
}
]
B - and I want it to be something like below.
[
{
"customerId": [5461321801, 5458122321]
"customerName": "C1"
},
{
"customerId": [5434315807],
"customerName": "C2"
}
]

Pure JS solution using Array.prototype.reduce() and Object.keys() functions:
var A = [
{ "customerId": 5458122321, "customerName": "C1" }, { "customerId": 5461321801, "customerName": "C1" }, { "customerId": 5434315807, "customerName": "C2" }
],
// accumulating an object "indexed" by 'customerName' attributes
// for grouping 'customers' by same name
B = A.reduce(function (r, o) {
(r[o.customerName])?
r[o.customerName]["customerId"].push(o.customerId)
: r[o.customerName] = {customerId: [o.customerId], customerName: o.customerName};
return r;
}, {}),
// getting values from the object 'B'
result = Object.keys(B).map(function(k){ return B[k]; });
console.log(result);

Here's a lodash solution that makes use of groupBy to group the collection by their customerName, map to transform each grouped items and then use map again to get all customerId in a grouped collection.
var result = _(source)
.groupBy('customerName')
.map(function(group, name) {
return {
customerId: _.map(group, 'customerId'),
customerName: name
};
}).value();
var source = [
{
"customerId": 5458122321,
"customerName": "C1"
},
{
"customerId": 5461321801,
"customerName": "C1"
},
{
"customerId": 5434315807,
"customerName": "C2"
}
];
var result = _(source)
.groupBy('customerName')
.map(function(group, name) {
return {
customerId: _.map(group, 'customerId'),
customerName: name
};
}).value();
console.log(result);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

solution with _.reduce
var B = _.reduce(A, function(result, item) {
var addedItem = _.find(result, {customerName: item.customerName});
if (addedItem) {
addedItem.customerId.push(item.customerId);
return result;
}
item.customerId = [item.customerId];
return _.concat(result, item);
}, []);

Related

How to push values to an object from inside a map function when a condition is met?

How can we push values to an object from inside a map function and return that single object. I have string comparison condition inside the map function. I tried using Object.assign but it returns an array with multiple object inside that array. Instead of this multiple object I'm expecting a single object inside an array.
Map function
let arrayObj = arrayToTraverse.map(function(item) {
var myObj = {};
if(item.inputvalue === 'Name'){
Object.assign(myObj, {name: item.value});
} else if (item.inputvalue === 'Email'){
Object.assign(organizerInfo, {email: item.value});
} else if (item.inputvalue === 'Company'){
Object.assign(organizerInfo, {company: item.value});
}
return myObj;
});
console.log("The array object is", arrayObj)
This return the array of objects as follows
[
{
"name": "Tom"
},
{
"email": "tom#abc.com"
},
{
"company": "ABC"
}
]
But The array I'm expecting is
[
{
"name": "Tom",
"email": "tom#abc.com",
"company": "ABC"
}
]
// or
[
"returned": {
"name": "Tom",
"email": "tom#abc.com",
"company": "ABC"
}
]
An example of arrayToTraverse can be considered as following
[
{
"id": "1",
"inputvalue": "Name",
"value": "Tom",
"type": "Short Text"
},
{
"id": "2",
"inputvalue": "Email",
"value": "tom#abc.com",
"type": "Email ID"
},
{
"id": "3",
"inputvalue": "Company",
"value": "Google",
"type": "Long Text"
}
]
Simply put, you're trying to reduce an array to a single object, not map one array to another.
var arrayToTraverse = [
{inputvalue:"Name",value:"Tom"},
{inputvalue:"Email",value:"tom#abc.com"},
{inputvalue:"Company",value:"ABC"},
{inputvalue:"Foo",value:"Bar"} // wont show up
];
var valuesRequired = ["Name","Email","Company"];
var result = arrayToTraverse.reduce( (acc, item) => {
if(valuesRequired.includes(item.inputvalue))
acc[item.inputvalue.toLowerCase()] = item.value;
return acc;
}, {});
console.log(result);
Edit: Added lookup array for required fields.

JS Creating a custom json by a nested json

Here I need to convert my nested JSON into a custom JSON without having nested objects.
function transform(){
let items = [
{
"carId":328288,
"firstName":"yathindra",
"lastName":"rawya",
"list":[
{
"id":182396,
"isAvail":false,
"stateId":288,
"state":"Awesome"
},
{
"id":182396,
"isAvail":false,
"stateId":678,
"state":"Cool1"
}
],
},
{
"carId":3282488,
"firstName":"yathindraR",
"lastName":"K",
"list":[
{
"id":18232396,
"isAvail":false,
"stateId":22388,
"state":"Awesome"
},
{
"id":182356796,
"isAvail":false,
"stateId":45678,
"state":"Cool"
}
],
}
]
let customList = [];
for(let i=0;i<items.length;i++){
let temp = new Array()
for(let j=0;j<items[i].list.length;j++){
temp.push(
items[i].list[j].state
)
}
customList.push({
fname: items[i].firstName,
lname: items[i].lastName,
...temp
})
}
console.log(JSON.stringify(customList))
}
transform();
Below is the output I am getting.
[{"0":"Awesome","1":"Cool1","fname":"yathindra","lname":"rawya"},{"0":"Awesome","1":"Cool","fname":"yathindraR","lname":"K"}]
But I don't want to place items in the temp array in the beginning. I want them to place at last.
Something like this.
[{"fname":"yathindra","lname":"rawya","0":"Awesome","1":"Cool1"},{"fname":"yathindraR","lname":"K","0":"Awesome","1":"Cool"}]
Here there is no need of using numbers as keys in the temp array. Because I want only values of each. So its ok if the keys of all are strings and order of values matters. How to make this done?
Please replace your code with below one, it will work straight away.
Key will be "state-1", "state-2" instead of "0", "1"
function transform(){
let items = [
{
"carId":328288,
"firstName":"yathindra",
"lastName":"rawya",
"list":[
{
"id":182396,
"isAvail":false,
"stateId":288,
"state":"Awesome"
},
{
"id":182396,
"isAvail":false,
"stateId":678,
"state":"Cool1"
}
],
},
{
"carId":3282488,
"firstName":"yathindraR",
"lastName":"K",
"list":[
{
"id":18232396,
"isAvail":false,
"stateId":22388,
"state":"Awesome"
},
{
"id":182356796,
"isAvail":false,
"stateId":45678,
"state":"Cool"
}
],
}
]
let customList = [];
for(let i=0;i<items.length;i++){
let temp = {};
for(let j=0;j<items[i].list.length;j++){
temp["state-"+(j+1)] = items[i].list[j].state;
}
customList.push({
fname: items[i].firstName,
lname: items[i].lastName,
...temp
})
}
console.log(JSON.stringify(customList))
}
transform();
Javascript Object first shows the sorted number list and then, the rest of the object's content as it is! run the following code and see what happens:D
console.log(JSON.stringify({1:true, b:false, 3:false}))
So if you want to keep your order, don't use numbers as keys!
Prepend your key with a zero, and then insertion order is maintained. In a CSV, that seems a good option.
If you want to use the spread operator, use an object instead of an array.
function transform() {
let items = [{
"carId": 328288,
"firstName": "yathindra",
"lastName": "rawya",
"list": [{
"id": 182396,
"isAvail": false,
"stateId": 288,
"state": "Awesome"
},
{
"id": 182396,
"isAvail": false,
"stateId": 678,
"state": "Cool1"
}
],
},
{
"carId": 3282488,
"firstName": "yathindraR",
"lastName": "K",
"list": [{
"id": 18232396,
"isAvail": false,
"stateId": 22388,
"state": "Awesome"
},
{
"id": 182356796,
"isAvail": false,
"stateId": 45678,
"state": "Cool"
}
],
}
]
let customList = [];
for (let i = 0; i < items.length; i++) {
let temp = {}
for (let j = 0; j < items[i].list.length; j++) {
temp['0' + j] = items[i].list[j].state
}
const o = {
fname: items[i].firstName,
lname: items[i].lastName,
...temp
}
customList.push(o)
}
console.log(JSON.stringify(customList))
}
transform();
That said, there are other ways you can map your items...
function transform() {
let items = [{
"carId": 328288,
"firstName": "yathindra",
"lastName": "rawya",
"list": [{
"id": 182396,
"isAvail": false,
"stateId": 288,
"state": "Awesome"
},
{
"id": 182396,
"isAvail": false,
"stateId": 678,
"state": "Cool1"
}
],
},
{
"carId": 3282488,
"firstName": "yathindraR",
"lastName": "K",
"list": [{
"id": 18232396,
"isAvail": false,
"stateId": 22388,
"state": "Awesome"
},
{
"id": 182356796,
"isAvail": false,
"stateId": 45678,
"state": "Cool"
}
],
}
]
let customList = items.map(item => {
let j = 0;
let list = item.list.reduce((acc, it) => {
acc['0' + j++] = it.state;
return acc
}, {})
return {
fname: item.firstName,
lname: item.lastName,
...list
}
})
console.log(JSON.stringify(customList))
}
transform();

Pivot or Transforming JavaScript object

I have the following JavaScript object. I need to generate a new object from the given object. What is the approach I should take in JavaScript?
[
{"name": "Dan", "city" : "Columbus", "ZIP":"47201"},
{"name": "Jen", "city" : "Columbus", "ZIP":"47201"},
{"name": "Mark", "city" : "Tampa", "ZIP":"33602"},
]
How can I transform or pivot to generate the following object?
[
{ "47201": [
{"name": "Dan", "city": "Columbus"},
{"name": "Jen", "city": "Columbus"},
],
"count": "2"
},
{ "33602": [
{"name": "Mark", "city": "Tampa"}
],
"count": "1"
}
]
I don't know why you want the .count property, when that can be accessed via the array's .length property, but anyway:
const input = [
{"name": "Dan", "city" : "Columbus", "ZIP":"47201"},
{"name": "Jen", "city" : "Columbus", "ZIP":"47201"},
{"name": "Mark", "city" : "Tampa", "ZIP":"33602"},
]
const working = input.reduce((acc, {ZIP, name, city}) => {
(acc[ZIP] || (acc[ZIP] = [])).push({name, city})
return acc
}, {})
const output = Object.keys(working)
.map(k => ({[k]: working[k], count: working[k].length}))
console.log(output)
Further reading:
Array .reduce()
Array .map()
Object.keys()
Unpacking fields from objects passed as function parameters
Computed property names
The below code will work for your requirement. The final result is stored in the variable result which holds the array object.
var source = [{
"name": "Dan",
"city": "Columbus",
"ZIP": "47201"
},
{
"name": "Mark",
"city": "Tampa",
"ZIP": "33602"
},
{
"name": "Jen",
"city": "Columbus",
"ZIP": "47201"
}
];
var result = [];
finalarr('ZIP');
function finalarr(propname) {
var obj = JSON.parse(JSON.stringify(source));
obj.forEach(function(elm,i) {
var arr = {};var chli=[];var charr={};
var flag = 0;
for (var prop in elm) {
if(prop != propname){
charr[prop]=elm[prop];
}
}
for(var i=0;i<result.length;i++){
if(result[i][elm[propname]]){
result[0][elm[propname]].push(charr);
//console.log(result[i][propname]);
flag = 1;
}
}
if(flag == 0){
chli.push(charr);
arr["count"] = checkarr(obj,propname,elm[propname]);
arr[elm[propname]]=chli;
result.push(arr);
}
});
}
function checkarr(obj,propname,value){
var count = 0;
obj.forEach(function(elm,i) {
if(elm[propname] == value){
count++;
}
});
return count;
}
console.log(result);

Organise element in a array

i'm searching a smart way to reoganise an array by a element inside it:
In entry i've got:
[{"name": "brevet",
"country": "fr"
},{
"name": "bac",
"country": "fr"
},{
"name": "des",
"country": "ca"
},{
"name": "dep",
"country": "ca"
}{
"name": "other",,
"country": "other"}]
I want to reorganize my array by country to have this in my output:
[{
"name": "fr",
"degrees": [
{
"name": "brevet",
"country": "fr"
},{
"name": "bac",
"country": "fr"
}]
},{
"name": "ca",
"degrees": [{
"name": "des",
"country": "ca"
},{
"name": "dep",
"country": "ca"
}]
},{
"name": "other",
"degrees": [{
"name": "other",
"country": "other"
}]
}]
For this i write a dirty function, but it seems to me there is a better way but i don't see how. If someone can ligth my brain in a better way to do this i'll be helpfull
private organizeDegrees(degrees: Array<SubscriptionFieldInterface>) {
let degreesByCountry = new Array();
let storeIndex = new Array();
degrees.map(degree => {
let index = null;
storeIndex.find((element, idx) => {
if (element === degree.country) {
index = idx;
return true;
}
});
if (index === null) {
index = degreesByCountry.length;
let newEntry = {
'name': degree.country,
'degrees': new Array()
};
storeIndex.push(degree.country);
degreesByCountry.push(newEntry);
}
degreesByCountry[index].degrees.push(degree);
});
return degreesByCountry;
}
thank's
You can group the array and map the object using Object.keys:
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
var grouped = groupBy(array, "country");
var mappedArray = Object.keys(grouped).map(key => ( {name: key, degrees: grouped [key]} ));
And one more way:
arr = [ /* your array */ ];
arr = Object.values(arr.reduce((ac, el) => {
if(!ac[el.country]) ac[el.country] = {"name": el.country, "degrees": []}
ac[el.country].degrees.push(el);
return ac
}, {}))
console.log(arr) // formated
Another solution, which also handles 'id' => '#id' mapping:
const a = [{"name":"brevet","country":"fr"},{"name":"bac","country":"fr"},{"id":73,"name":"des","country":"ca"},{"name":"dep","country":"ca"},{"name":"other","country":"other"}];
const r = [...new Set(a.map(({country}) => country))] // list of unique country names
.map(c => Object.assign({name: c}, // for each country
{degrees: a.filter(x => x.country === c).map(y => Object.keys(y).includes('id') // handle 'id' => '#id' mutation
? {'#id': "/subscription_fields/" + y.id, name: y.name, country: y.country}
: y)
}))
console.log(r)
This is purely ES6, and quite terse, but possibly less readable. Also, it doesn't add the "#id": "/subscription_fields/83", which could be added as a post process:
const groupByKey = (arr, key) => [...arr.reduce((acc, deg) =>
acc.set(deg[key], {name: deg[key], degrees: [ ...(acc.get(deg[key]) || {degrees: []}).degrees, deg]})
, new Map()).values()];
console.log(groupByKey(degrees, 'country'));
You could use a hash table and collect all values in an object. For getting the result array, you need to push the object only once.
var data = [{ name: "brevet", country: "fr" }, { name: "bac", country: "fr" }, { id: 73, name: "des", country: "ca" }, { name: "dep", country: "ca" }, { name: "other", country: "other" }],
result = data.reduce(function (hash) {
return function (r, a) {
if (!hash[a.country]) {
hash[a.country] = { name: a.country, degrees: [] };
r.push(hash[a.country]);
}
hash[a.country].degrees.push({ name: a.name, country: a.country });
return r;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Create arrays from JavaScript objects

I have some data which looks like this:
{
"obj":
[
{
"name": "name1",
"age": "24"
},
{
"name": "name2",
"age": "17"
}
]
}
What I need to do is to create 2 arrays from it.
For example:
namelist[];
agelist[];
so the result would be:
namelist: ['name1', 'name2'];
agelist: [24, 17];
My question is, how can I do this?
var namelist = [];
var agelist = [];
for(var i in obj.obj){
namelist.push(obj.obj[i].name);
agelist.push(obj.obj[i].age);
}
console.log(namelist, agelist);
Is this what U wanted ?
var zz={
"obj": [
{
"name": "name1",
"age": "24"
},
{
"name": "name2",
"age": "17"
}
]
}
namelist=[];
agelist=[];
zz.obj.forEach(function(rec){
namelist.push(rec.name);
agelist.push(rec.age);
})
console.log(namelist,agelist)
You could use this ES6 code, and use the unitary plus for getting the ages as numbers. Assuming your object is stored in variable data:
var namelist = data.obj.map( o => o.name );
var agelist = data.obj.map( o => +o.age );
var data = {
"obj": [
{
"name": "name1",
"age": "24"
},
{
"name": "name2",
"age": "17"
}
]
};
var namelist = data.obj.map( o => o.name );
var agelist = data.obj.map( o => +o.age );
console.log(namelist);
console.log(agelist);
var arr = $.map(myObj, function(value, index) {
return [value];
});
console.log(arr);
if you are not using Jquery then:
var arr = Object.keys(myObj).map(function (key)
{ return obj[key];
});`
Make use of jquery map function or otherwise you can loop over the object and push it into array using javascript for loop and use the push() function. Refer Loop through an array in JavaScript
Jquery
var data = {
"obj": [
{
"name": "name1",
"age": "24"
},
{
"name": "name2",
"age": "17"
}
]
}
var name = $.map(data.obj, function(value, index) {
return value.name;
});
var age = $.map(data.obj, function(value, index) {
return value.age;
});
console.log(name);
console.log(age);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Javascript
var data = {
"obj": [
{
"name": "name1",
"age": "24"
},
{
"name": "name2",
"age": "17"
}
]
}
var names = [], ages=[];
data.obj.forEach(function(value, index) {
names.push(value.name);
ages.push(value.age);
});
console.log(names,ages);

Categories

Resources