var customersObj= [
{ recordId: "123", groupID: "1992" ,memberID:"10" Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
I need to return the array by sort them first by recordId, then by groupID, then by memberID ...
I tried this but didn't get expected result"
return _.sortBy(customersObj,'recordID','groupID','memberID');
Can someone assist here on this...
Pay attention that your *ID are strings, so, I've used Array.map to convert them to ints, and then _.sortBy works expectedly.
I've added additional values to check the sub-sorting.
const customersObj = [{
recordId: "123",
groupID: "1992",
memberID: "10",
Name: "John"
}, {
recordId: "141",
groupID: "1994",
memberID: "13",
Name: "Arrow"
}, {
recordId: "111",
groupID: "1991",
memberID: "12",
Name: "Mike"
}, {
recordId: "123",
groupID: "1991",
memberID: "12",
Name: "Sean"
}, {
recordId: "123",
groupID: "1991",
memberID: "11",
Name: "Sara"
}];
const result = customersObj.map(item => ({
recordId: parseInt(item.recordId, 10),
groupID: parseInt(item.groupID, 10),
memberID: parseInt(item.memberID, 10),
Name: item.Name
}));
console.log(_.sortBy(result, 'recordId', 'groupID', 'memberID'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
Try use this approach:
const customersObj= [
{ recordId: "123", groupID: "1992" ,memberID:"10", Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
const sorted = customersObj.sort((a,b)=>{
return a.recordId - b.recordId || a.groupID - b.groupID || a.memberID - b.memberID;
})
console.log(`sorted`, sorted);
you can use sort method with lambda function to sort.
const list = [
{ color: 'white', size: 'XXL' },
{ color: 'red', size: 'XL' },
{ color: 'black', size: 'M' }
]
list.sort((a, b) => (a.color > b.color) ? 1 : -1) // you can add different conditions here.
to sort multiple fields, do it like this
customersObj.sort(function(a, b) {
return a["recordId"] - b["recordId"] || a["groupID"] - b["groupID"] || a["memberID"] - b["memberID"];
});
You can sort array of object using multiple values by the following method
var arrayOfObj = [
{ recordId: "123", groupID: "1992" ,memberID:"10" , Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
let sortBy = [{
prop:'recordId',
direction: 1
},{
prop:'lastName',
direction: 1
},{
prop:'memberID',
direction: 1
}];
arrayOfObj.sort(function(a,b){
let i = 0, result = 0;
while(i < sortBy.length && result === 0) {
result = sortBy[i].direction*(a[ sortBy[i].prop ].toString() < b[ sortBy[i].prop ].toString() ? -1 : (a[ sortBy[i].prop ].toString() > b[ sortBy[i].prop ].toString() ? 1 : 0));
i++;
}
return result;
})
console.log(arrayOfObj, ":::::");
With lodash, could take an array of keys and take the right spelling of the wanted keys.
var customersObj = [{ recordId: "123", groupID: "1992", memberID: "10", Name: "John" }, { recordId: "141", groupID: "1994", memberID: "13", Name: "Arrow" }, { recordId: "111", groupID: "1991",
memberID: "12", Name: "Mike" }];
console.log(_.sortBy(customersObj, ['recordId', 'groupID', 'memberID']));
// ^ ^ ^
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Hi i tried solve your problem :)
const display = document.querySelector(".display");
var customersObj= [
{ recordId: "123", groupID: "1992" ,memberID:"10", Name : "John" },
{ recordId: "141", groupID: "1994" ,memberID:"13", Name : "Arrow" },
{ recordId: "111", groupID: "1991",memberID:"12", Name : "Mike" }
];
customersObj.sort(function (a, b) {
return a.recordId - b.recordId || b.groupID - a.groupID || c.memberID - c.memberID;
});
customersObj.map(obj => {
const item = document.createElement("div");
item.textContent += obj.recordId + " " + obj.groupID + " " + obj.memberID +" "+ obj.Name;
display.appendChild(item);
});
<div class="display">
</div>
Related
i am trying to find a list of synced users between two arrays (objArray1 & objArray2) and return the data from objArray1 along with 'aid' in Objarray2. I have the below code working, but i am trying to see if can return 'aid' from objArray2 as well in the below format.
Code sample below
// SystemA
const objArray1 = [
{ id: "1", name: "John" },
{ id: "2", name: "Jack" },
{ id: "3", name: "Sam" },
{ id: "4", name: "Bill" },
];
// SystemB
const objArray2 = [
{ id: "1", name: "John", aid:"uuud2905555" },
{ id: "3", name: "Sam" }, aid:"uuud29029303"
{ id: "5", name: "Bob" }, aid:"uuud29435454"
];
const array1IDs = objArray1.map((item) => {
return item.id
})
// Result: array1IDs = ["1", "2", "3", "4"];
const array2IDs = objArray2.map((item) => {
return item.id
})
// Result: array2IDs = ["1", "3", "5"];
// FIND SYNCED USERS
// Compare the id value of each item in objArray1 with each item of objArray2
// Return the ones that match.
const syncedUsers = objArray1.filter((item) => {
const found = objArray2.find((element) => element.id === item.id);
return found;
});
Required JSON Format, please note that all matching items should be returned from objArray1, with the exception of 'aid' from objArray2
{
"records": [
{
"id": {aid}, // from objArray2
"fields": {
"Name":{name}, // from objArray1
"sid": {id} // from objArray1
}
]
}
Presented below is one possible way to achieve the desired objective.
Code Snippet
// method to create result as "JSON"
const createJSON = (arr1, arr2) => (
// use "stringify" to transform JavaScript object into JSON
JSON.stringify({
// set-up the "records" prop
records: arr2
.filter( // filter to keep only those that have matching "id"
({ id }) => arr1.some(ob => ob.id === id)
)
.map( // de-structure & rename props to match desired objective
({ id : sid, name : Name, aid: id }) => ({
id,
fields: {Name, sid}
})
)
})
);
// SystemA
const objArray1 = [
{ id: "1", name: "John" },
{ id: "2", name: "Jack" },
{ id: "3", name: "Sam" },
{ id: "4", name: "Bill" },
];
// SystemB
const objArray2 = [
{ id: "1", name: "John", aid:"uuud2905555" },
{ id: "3", name: "Sam", aid:"uuud29029303" },
{ id: "5", name: "Bob", aid:"uuud29435454" },
];
console.log('result as a JSON: ', createJSON(objArray1, objArray2));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.
EDIT
Use name and id from array-1. Used restOfArr1Props to account for all other props of array-1 objects to be included.
const createJSON = (arr1, arr2) => (
JSON.stringify({
records: arr1
.filter(
({ id }) => arr2.some(ob => ob.id === id)
)
.map(
({ id : sid, name : Name, ...restOfArr1Props }) => ({
id: arr2.find(a2 => a2.id === sid)?.aid ?? 'missing aid',
fields: {
Name, sid, ...restOfArr1Props
},
})
)
})
);
// SystemA
const objArray1 = [
{ id: "1", name: "John", prop1: 'value11', prop2: 'value12' },
{ id: "2", name: "Jack", prop1: 'value21', prop2: 'value22' },
{ id: "3", name: "Sam", prop1: 'value31', prop2: 'value32' },
{ id: "4", name: "Bill", prop1: 'value41', prop2: 'value42' },
];
// SystemB
const objArray2 = [
{ id: "1", name: "John", aid:"uuud2905555" },
{ id: "3", name: "Sam", aid:"uuud29029303" },
{ id: "5", name: "Bob", aid:"uuud29435454" },
];
console.log('result as a JSON: ', createJSON(objArray1, objArray2));
.as-console-wrapper { max-height: 100% !important; top: 0 }
const objArray1 = [
{ id: '1', name: 'John', type: 'bully' },
{ id: '2', name: 'Jack', type: 'sporty' },
{ id: '3', name: 'Sam', type: 'kind' },
{ id: '4', name: 'Bill', type: 'poliet' },
];
const objArray2 = [
{ id: '1', name: 'John', aid: 'uuud2905555' },
{ id: '3', name: 'Sam', aid: 'uuud29029303' },
{ id: '5', name: 'Bob', aid: 'uuud29435454' },
];
const syncedUsers = { records: [] };
for (let user1 of objArray1) {
const foundUser = objArray2.find(user2 => user2.id === user1.id);
if (foundUser) {
syncedUsers.records.push({
id: foundUser.aid,
fields: { sid: user1.id, name: user1.name, ...user1 },
});
}
}
console.log(JSON.stringify(syncedUsers));
With a API call i'm receiving a response like below
[
{
stationId: "10"
name: "Jinbaolai"
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "13"
name: "Stack"
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "20"
name: "Overflow"
group: {id: "19", stationGroupName: "Baba"}
}
]
As you can see first two records consist with the same group. I want to group these data according to the group. So for example it should look like this
[
{
groupId: "18",
groupName : "Ali",
stations : [
{
stationId: "10",
name: "Jinbaolai"
},
{
stationId: "13",
name: "Stack"
}
]
},
{
groupId: "19",
groupName : "Baba",
stations : [
{
stationId: "20",
name: "Overflow"
},
]
}
]
I want to do the grouping logic in my reducer where i also set the full data array that is shown in the beginning of the question.
case EVC_SUCCESS:
return {
...state,
chargingStations: action.evcData.chargingStations,
chargingStationGroups: //This is where my logic should go. ('action.evcData.chargingStations' is the initial data array)
tableLoading: false
}
How can i do this? I tried something using filter but not successful.
The best way to do this is to use Array.prototype.reduce()
Reduce is an aggregating function where you put in an array of something and get a single vaule back.
There may be a starting value as last parameter like I used {}.
The signature is reduce(fn, startingValue) where fn is a function taking two parameters aggregate and currentValue where you return the aggregate in the end.
const groupData = (data)=> {
return Object.values(data.reduce((group,n)=>{
if (!group[n.group.id]){
group[n.group.id] = {
groupId:n.group.id,
groupName: n.group.stationGroupName,
stations:[]}
}
group[n.group.id].stations.push({
stationID: n.stationId,
name: n.name
})
return group;
}, {}))
}
Here is the fiddle
A simple JS algorithm can do that for you
const list = [
{
stationId: "10",
name: "Jinbaolai",
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "13",
name: "Stack",
group: {id: "18", stationGroupName: "Ali"}
},
{
stationId: "20",
name: "Overflow",
group: {id: "19", stationGroupName: "Baba"}
}
];
const groups = {};
list.forEach((item) => {
const groupId = item.group.id;
const group = groups[groupId] || {groupId: groupId, groupName: item.group.stationGroupName, stations: []};
group.stations.push({stationId: item.stationId, name: item.name});
groups[groupId] = group;
});
const groupedArray = Object.keys(groups).map((groupId) => groups[groupId]);
console.log(groupedArray); // This will be the output you want
I think chaining multiple functions will work.
const stations = [
{
"stationId": 10,
"name": "Jinbaolai",
"group": {"id": "18", "stationGroupName": "Ali"}
},
{
"stationId": 13,
"name": "Stack",
"group": {"id": 18, "stationGroupName": "Ali"}
},
{
"stationId": 20,
"name": "Overflow",
"group": {"id": "19", "stationGroupName": "Baba"}
}
]
const groups = _.chain(stations)
.groupBy((station) => { return station.group.id })
.map((values, key) => {
return {
"groupId": _.first(values).group.id,
"groupName": _.first(values).group.id,
"stations": _.map(values,(value)=>{ return { "stationId": value.stationId, "name": value.name } })
}
})
console.log("groups",groups)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
I have a array of makes as follows:
const makes = [
{id: "4", name: "Audi"},
{id: "5", name: "Bmw"},
{id: "6", name: "Porsche"},
{id: "31", name: "Seat"},
{id: "32", name: "Skoda"},
{id: "36", name: "Toyota"},
{id: "38", name: "Volkswagen"}
]
And I want to sort that array based on another array:
const preferred_makes = ['Volkswagen', 'Audi'];
What I do now is as follows:
const preferred_makes = ['Volkswagen', 'Audi'];
const makes = [
{id: "4", name: "Audi"},
{id: "5", name: "Bmw"},
{id: "6", name: "Porsche"},
{id: "31", name: "Seat"},
{id: "32", name: "Skoda"},
{id: "36", name: "Toyota"},
{id: "38", name: "Volkswagen"}
]
const mainMakes = []
const otherMakes = []
makes.map(make => _.includes(preferred_makes, make.name) ? mainMakes.push(make) : otherMakes.push(make))
console.log(mainMakes)
console.log(otherMakes)
But is there any better way? Can I sort makes to show those preferred_makes as first elements of the array?
Here is the fiddle.
A regular array.sort() with a custom comparison function should be able to do this.
const preferred_makes = ['Volkswagen', 'Audi'];
const makes = [
{id: "4", name: "Audi"},
{id: "5", name: "Bmw"},
{id: "6", name: "Porsche"},
{id: "31", name: "Seat"},
{id: "32", name: "Skoda"},
{id: "36", name: "Toyota"},
{id: "38", name: "Volkswagen"}
]
const sorted = makes.slice().sort((a, b) => {
// Convert true and false to 1 and 0
const aPreferred = new Number(preferred_makes.includes(a.name))
const bPreferred = new Number(preferred_makes.includes(b.name))
// Return 1, 0, or -1
return bPreferred - aPreferred
})
console.log(sorted)
You could take an object with the by one incremented indices and take a default value of Infinity for not found names. Then sort by the delta of the values.
var preferred_makes = ['Volkswagen', 'Audi'],
preferred = preferred_makes.reduce((o, k, i) => (o[k] = i + 1, o), {});
array = [{ id: "4", name: "Audi" }, { id: "5", name: "Bmw" }, { id: "6", name: "Porsche" }, { id: "31", name: "Seat" }, { id: "32", name: "Skoda" }, { id: "36", name: "Toyota" }, { id: "38", name: "Volkswagen" }];
array.sort((a, b) => (preferred[a.name] || Infinity) - (preferred[b.name] || Infinity));
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use reduce to make two arrays without the requirement for sorting:
const preferred_makes = ['Volkswagen','Audi'];
const makes = [{id:"4",name:"Audi"},{id:"5",name:"Bmw"},{id:"6",name:"Porsche"},{id:"31",name:"Seat"},{id:"32",name:"Skoda"},{id:"36",name:"Toyota"},{id:"38",name:"Volkswagen"}];
const [mainMakes, otherMakes] = makes.reduce(([a, b], { id, name }) => ((preferred_makes.includes(name) ? a : b).push({ id, name }), [a, b]), [[], []]);
console.log(mainMakes);
console.log(otherMakes);
.as-console-wrapper { max-height: 100% !important; top: auto; }
To make it even faster, you could Set.prototype.has instead of includes:
const preferred_makes = new Set(['Volkswagen','Audi']);
const makes = [{id:"4",name:"Audi"},{id:"5",name:"Bmw"},{id:"6",name:"Porsche"},{id:"31",name:"Seat"},{id:"32",name:"Skoda"},{id:"36",name:"Toyota"},{id:"38",name:"Volkswagen"}];
const [mainMakes, otherMakes] = makes.reduce(([a, b], { id, name }) => ((preferred_makes.has(name) ? a : b).push({ id, name }), [a, b]), [[], []]);
console.log(mainMakes);
console.log(otherMakes);
.as-console-wrapper { max-height: 100% !important; top: auto; }
With lodash you can generate a dictionary of the original index by the car's make (indexByMake) using _.invert() to get an object of { [car make]: original array index }, and map the values back to numbers.
Use _.orderBy() to sort the array, and use the values from indexByMake according to the name:
const preferred_makes = ['Volkswagen', 'Audi'];
const array = [{ id: "4", name: "Audi" }, { id: "5", name: "Bmw" }, { id: "6", name: "Porsche" }, { id: "31", name: "Seat" }, { id: "32", name: "Skoda" }, { id: "36", name: "Toyota" }, { id: "38", name: "Volkswagen" }];
const indexByMake = _.mapValues(_.invert(preferred_makes), Number);
const result = _.sortBy(array, ({ name }) => indexByMake[name]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
You can also sort by the Array.indexOf if the index is there otherwise use String.localeCompare. No real need for lodash really:
const makes = [ {id: "4", name: "Audi"}, {id: "6", name: "Porsche"}, {id: "31", name: "Seat"}, {id: "32", name: "Skoda"}, {id: "5", name: "Bmw"}, {id: "36", name: "Toyota"}, {id: "38", name: "Volkswagen"} ]
const list = ['Volkswagen', 'Audi'];
let result = makes.sort((a,b) => {
let i = list.indexOf(a.name)
return i < 0 ? a.name.localeCompare(b.name) : list.indexOf(b.name) - i
})
console.log(result)
I would like to know how to remove the object by property in nested array object
I have whole list of object in sampleobj, compare each id with apitrans, apifund, if success is false, remove obj in sampleobj
Remove the object if the success is false, in sampleobj.
I have tried:
var result = sampleobj.foreach(e=>{
if(e.id === "trans" && apitrans.success== true){
Object.assign(e, apitrans);
}
if(e.id === "fund" && apifund.success== true){
Object.assign(e, apifund);
}
// if success false remove the object.
})
//inputs scenario 1
var sampleobj=[{
id: "trans",
amount: "100",
fee: 2
},
{
id: "fund",
amount: "200",
fee: 2
}]
var apitrans =
{
success: true,
id: "trans",
tamount: "2000",
fee: "12"
}
var apifund =
{
success: false,
id: "fund",
tamount: "4000",
fee: "10"
}
//inputs scenario 2 how to do same if property name differs
if error, status error, or success false remove obj in sampleobj
var sampleobj=[{
id: "trans",
amount: "100",
fee: 2
},
{
id: "fund",
amount: "200",
fee: 2
},
{ id: "insta", amount: "400", fee: 2 }
]
var apitrans = {success: true,id: "trans",tamount: "2000",fee: "12"}
var apiinsta = { errors: [{code:"error.route.not.supported"}],id: "insta",tamount: "2000",fee: "12"}
var apifund = { status: "error", id: "fund", tamount: "4000", fee: "10" }
var sampleobj=[{
//Expected Output
result: [
{
id: "trans",
amount: "100",
fee: 2
}
]```
You can use filter() to remove elements from array.
Create a helper function(func) which takes two objects as parameter and compare id property of both and check success property of one of them.
Then use filter() of the given array and put both given objects array [apitrans,apifund].
Then use some() method on [apitrans,apifund] and check if any of them have id equal the current element using Helper Function.
var arr=[ { id: "trans", amount: "100", fee: 2 }, { id: "fund", amount: "200", fee: 2 } ]
var apitrans = {success: true,id: "trans",tamount: "2000",fee: "12"}
var apifund = { success: false, id: "fund", tamount: "4000", fee: "10" }
const func = (obj1,obj2) => obj1.id === obj2.id && obj2.success
const res = arr.filter(x => [apitrans,apifund].some(a => func(x,a)));
console.log(res)
You can filter out your array with conditions i.e filter gives you new array instead of changing the original array
var arr = [{
id: "trans",
amount: "100",
fee: 2
},
{
id: "fund",
amount: "200",
fee: 2
}
]
var apitrans = {
success: true,
id: "trans",
tamount: "2000",
fee: "12"
}
var apifund = {
success: false,
id: "fund",
tamount: "4000",
fee: "10"
}
var filter = arr.filter(function(item) {
//console.log(item);
if (item.id === apitrans.id && apitrans.success) {
return item
}
});
console.log(filter);
Or if you want an original array to be modified instead of getting a new array, you can use your given approach with some update i.e
var arr = [{
id: "trans",
amount: "100",
fee: 2
},
{
id: "fund",
amount: "200",
fee: 2
}
]
var apitrans = {
success: true,
id: "trans",
tamount: "2000",
fee: "12"
}
var apifund = {
success: false,
id: "fund",
tamount: "4000",
fee: "10"
}
arr.forEach(e => {
if (e.id === "trans" && apitrans.success == true) {
Object.assign(e, apitrans);
} else if (e.id === "fund" && apifund.success == true) {
Object.assign(e, apifund);
} else {
// if success false remove the object.
var index = arr.indexOf(e);
arr.splice(index, 1);
}
})
console.log("resulted original arr", arr)
EDIT: Thanks for the replies!
I am kind of new to working with Javascript (sorry for probably the bad code). I've mainly only worked with HTML and CSS. I have been trying to experiment with Javascript, but I've been stuck on this forever. The outcome is not what I want it to be.
My code:
I want to make the array easier to use, by putting the values under the same category, but my code's output is not exactly what I want it to be like.
var data = {
idName: "idName",
valueRanges: [{
range: "range",
majorDimension: "ROWS",
values: [
[
"ID",
"Category",
"Name"
],
[
"1",
"Category1",
"Name1"
],
[
"2",
"Category1",
"Name2"
],
[
"3",
"Category2",
"Name3"
],
[
"4",
"Category1",
"Name4"
]
]
}]
}
var rows = [];
let batchRowValues = data.valueRanges[0].values
for (let i = 1; i < batchRowValues.length; i++) {
let rowObject = {};
for (let j = 0; j < batchRowValues[i].length; j++) {
rowObject[batchRowValues[0][j]] = batchRowValues[i][j];
}
rows.push(rowObject);
}
var newArray = rows.reduce(function(acc, curr) {
var findIfNameExist = acc.findIndex(function(item) {
return item.Category === curr.Category;
})
if (findIfNameExist === -1) {
let obj = {
'Category': curr.Category,
'value': [curr]
}
acc.push(obj)
} else {
acc[findIfNameExist].value.push(curr)
}
return acc;
}, []);
console.log('------------')
console.log('input: ' + JSON.stringify(data, null, 2))
console.log('------------')
console.log('output: ' + JSON.stringify(newArray, null, 2))
My code's output:
[
{
Category: "Category1",
value: [
{
Category: "Category1",
ID: "1",
Name: "Name1"
},
{
Category: "Category1",
ID: "2",
Name: "Name2"
},
{
Category: "Category1",
ID: "4",
Name: "Name4"
}
]
},
{
Category: "Category2",
value: [
{
Category: "Category2",
ID: "3",
Name: "Name3"
}
]
}
]
How I want it to look:
[
{
Category: "Category1",
values: [
{
ID: "1",
Name: "Name1"
},
{
ID: "2",
Name: "Name2"
},
{
ID: "4",
Name: "Name4"
}
]
},
{
Category: "Category2",
values: [
{
ID: "3",
Name: "Name3"
},
]
},
]
I want to learn! I appreciate any help.
You can use reduce.
Here idea is
Create a object and use category as key
If a category is already found than push the desired object in it's value property. if not than we create a new one with suitable data.
I am using object here instead of array directly is because i can directly access element using key where as in array i need to loop through each time and check existence of value
var data = {idName: "idName",valueRanges: [{range: "range",majorDimension: "ROWS",values: [["ID","Category","Name"],["1","Category1","Name1"],["2","Category1","Name2"],["3","Category2","Name3"],["4","Category1","Name4"]]}]}
var rows = [];
let batchRowValues = data.valueRanges[0].values.slice(1,)
let op = batchRowValues.reduce((op,[ID,Category,Name]) => {
if( op[Category] ){
op[Category].value.push({ID,Name})
} else {
op[Category] = {
Category,
value: [{ID,Name}]
}
}
return op
},{})
console.log(Object.values(op))
Try (t={}, result in r)
data.valueRanges[0].values.slice(1).map( ([i,c,n])=>
(t[c]=t[c]||{Category:c,values:[]}, t[c].values.push({ID:i, Name:n})) );
let r= Object.values(t);
var data =
{
idName: "idName",
valueRanges: [
{
range: "range",
majorDimension: "ROWS",
values: [
[
"ID",
"Category",
"Name"
],
[
"1",
"Category1",
"Name1"
],
[
"2",
"Category1",
"Name2"
],
[
"3",
"Category2",
"Name3"
],
[
"4",
"Category1",
"Name4"
]
]
}
]
}
let t={};
data.valueRanges[0].values.slice(1).map( ([i,c,n])=>
(t[c]=t[c]||{Category:c,values:[]}, t[c].values.push({ID:i, Name:n})) );
let r= Object.values(t);
console.log(r);